> getReceivablePriceStaffPerformance(@Valid CrmStatisticsPerformanceReqVO performanceReqVO) {
+ return success(performanceService.getReceivablePricePerformance(performanceReqVO));
+ }
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java
index 986e226..986e226 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsPortraitController.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http
index 407562d..407562d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.http
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java
index 974963d..974963d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/CrmStatisticsRankController.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java
index bde0029..bde0029 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerByUserBaseRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java
index fa03d46..fa03d46 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerContractSummaryRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByAreaRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByAreaRespVO.java
index 3698378..3698378 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByAreaRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByAreaRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java
index 62facb0..62facb0 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByDateRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByProductRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByProductRespVO.java
index 442c195..442c195 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByProductRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByProductRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java
index 1c394b8..1c394b8 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerDealCycleByUserRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java
index b32a35e..b32a35e 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerReqVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java
index 7ffcb20..7ffcb20 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByDateRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java
index fa8372b..fa8372b 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsCustomerSummaryByUserRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByDateRespVO.java
index 9040c1e..9040c1e 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByDateRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByTypeRespVO.java
index d39f1cc..d39f1cc 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByTypeRespVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByUserRespVO.java
index 0651356..0651356 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsFollowUpSummaryByUserRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByDateRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByDateRespVO.java
index ce09a99..ce09a99 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByDateRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByDateRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByUserRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByUserRespVO.java
index fb59e84..fb59e84 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByUserRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/customer/CrmStatisticsPoolSummaryByUserRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelSummaryRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelSummaryRespVO.java
index 38d1c11..38d1c11 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelSummaryRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticFunnelSummaryRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessInversionRateSummaryByDateRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessInversionRateSummaryByDateRespVO.java
index b7650a9..b7650a9 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessInversionRateSummaryByDateRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessInversionRateSummaryByDateRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java
index 1f8056c..1f8056c 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByDateRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByEndStatusRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByEndStatusRespVO.java
index 023fdb8..023fdb8 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByEndStatusRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsBusinessSummaryByEndStatusRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java
index dac3406..dac3406 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/funnel/CrmStatisticsFunnelReqVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java
index bfb5c84..952ee3d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceReqVO.java
@@ -1,41 +1,41 @@
-package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.time.LocalDateTime;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-@Schema(description = "管理后台 - CRM 员工业绩统计 Request VO")
-@Data
-public class CrmStatisticsPerformanceReqVO {
-
- @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
- @NotNull(message = "部门 id 不能为空")
- private Long deptId;
-
- /**
- * 负责人用户 id, 当用户为空, 则计算部门下用户
- */
- @Schema(description = "负责人用户 id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
- private Long userId;
-
- /**
- * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
- *
- * 后续,可能会支持选择部分用户进行查询
- */
- @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
- private List userIds;
-
- @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- @NotEmpty(message = "时间范围不能为空")
- private LocalDateTime[] times;
-
-}
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - CRM 员工业绩统计 Request VO")
+@Data
+public class CrmStatisticsPerformanceReqVO {
+
+ @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "部门 id 不能为空")
+ private Long deptId;
+
+ /**
+ * 负责人用户 id, 当用户为空, 则计算部门下用户
+ */
+ @Schema(description = "负责人用户 id", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
+ private Long userId;
+
+ /**
+ * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
+ *
+ * 后续,可能会支持选择部分用户进行查询
+ */
+ @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
+ private List userIds;
+
+ @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ @NotEmpty(message = "时间范围不能为空")
+ private LocalDateTime[] times;
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java
index 8b217fd..480e219 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/performance/CrmStatisticsPerformanceRespVO.java
@@ -1,24 +1,24 @@
-package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import java.math.BigDecimal;
-
-
-@Schema(description = "管理后台 - CRM 员工业绩统计 Response VO")
-@Data
-public class CrmStatisticsPerformanceRespVO {
-
- @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401")
- private String time;
-
- @Schema(description = "当月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
- private BigDecimal currentMonthCount;
-
- @Schema(description = "上月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
- private BigDecimal lastMonthCount;
-
- @Schema(description = "去年同期统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
- private BigDecimal lastYearCount;
-
-}
+package cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import java.math.BigDecimal;
+
+
+@Schema(description = "管理后台 - CRM 员工业绩统计 Response VO")
+@Data
+public class CrmStatisticsPerformanceRespVO {
+
+ @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401")
+ private String time;
+
+ @Schema(description = "当月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private BigDecimal currentMonthCount;
+
+ @Schema(description = "上月统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+ private BigDecimal lastMonthCount;
+
+ @Schema(description = "去年同期统计结果", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
+ private BigDecimal lastYearCount;
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java
index 3420e7e..3420e7e 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerAreaRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java
index 84b8de7..84b8de7 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerIndustryRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java
index dea4eeb..dea4eeb 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerLevelRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java
index 61b9688..61b9688 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticCustomerSourceRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticsPortraitReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticsPortraitReqVO.java
index d164151..d164151 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticsPortraitReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/portrait/CrmStatisticsPortraitReqVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankReqVO.java
index c9b1ae7..c9b1ae7 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankReqVO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankReqVO.java
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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java
index feb2f3f..feb2f3f 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/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/statistics/vo/rank/CrmStatisticsRankRespVO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java
index 78d8563..78d8563 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/app/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java
index 8354b31..8354b31 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java
index 6fbc525..6fbc525 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/convert/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
index 8153487..8153487 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
index a30ece2..a30ece2 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
index 2f66fc3..2f66fc3 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java
index 5d7b8bd..5d7b8bd 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
index 95b7a1f..95b7a1f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessStatusTypeDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
index 3af6fee..3af6fee 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java
index 929b9b6..929b9b6 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java
index 46185a5..46185a5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java
index 5a891eb..5a891eb 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java
index dfe0898..dfe0898 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java
index ab0c2d2..ab0c2d2 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractConfigDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
index 89f4fd9..89f4fd9 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java
index 6bb3e6b..6bb3e6b 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
index 76d5111..76d5111 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerLimitConfigDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerLimitConfigDO.java
index df3d3be..df3d3be 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerLimitConfigDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerLimitConfigDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerPoolConfigDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerPoolConfigDO.java
index 76f20dc..76f20dc 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerPoolConfigDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerPoolConfigDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java
index a01d47a..a01d47a 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
index 59e47a5..59e47a5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/permission/CrmPermissionDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductCategoryDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductCategoryDO.java
index e0f4d62..e0f4d62 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductCategoryDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductCategoryDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
index caeeb53..caeeb53 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java
index 4c7282d..4c7282d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java
index c24614a..c24614a 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivableDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java
index 5ddefc5..5ddefc5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/receivable/CrmReceivablePlanDO.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
index 894ab32..894ab32 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java
index a91a0fd..a91a0fd 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java
index dfe7afc..dfe7afc 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java
index 3444e58..3444e58 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessStatusTypeMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
index 88650dc..88650dc 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java
index f9978e8..f9978e8 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java
index 7bff0c2..7bff0c2 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
index 06114ae..06114ae 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java
index 64e6f91..64e6f91 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractConfigMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
index 1303112..1303112 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java
index feafbc4..feafbc4 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java
index 08beaf8..08beaf8 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
index 6be1186..6be1186 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerPoolConfigMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerPoolConfigMapper.java
index 06cf44e..06cf44e 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerPoolConfigMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerPoolConfigMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java
index 45e2b41..45e2b41 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
index 07b7b6b..07b7b6b 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java
index ff0e16b..ff0e16b 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductCategoryMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductCategoryMapper.java
index 3cced73..3cced73 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductCategoryMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductCategoryMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java
index 4d1d618..4d1d618 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
index 904357e..904357e 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
index e9e28b8..e9e28b8 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
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/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java
index 171d432..171d432 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/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsCustomerMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsFunnelMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsFunnelMapper.java
index d69fa62..d69fa62 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsFunnelMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsFunnelMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java
index 09702f2..6467a09 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPerformanceMapper.java
@@ -1,41 +1,41 @@
-package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
-
-import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
-import org.apache.ibatis.annotations.Mapper;
-
-import java.util.List;
-
-/**
- * CRM 员工业绩分析 Mapper
- *
- * @author scholar
- */
-@Mapper
-public interface CrmStatisticsPerformanceMapper {
-
- /**
- * 员工签约合同数量
- *
- * @param performanceReqVO 参数
- * @return 员工签约合同数量
- */
- List selectContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
-
- /**
- * 员工签约合同金额
- *
- * @param performanceReqVO 参数
- * @return 员工签约合同金额
- */
- List selectContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
-
- /**
- * 员工回款金额
- *
- * @param performanceReqVO 参数
- * @return 员工回款金额
- */
- List selectReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
-
-}
+package cn.iocoder.yudao.module.crm.dal.mysql.statistics;
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * CRM 员工业绩分析 Mapper
+ *
+ * @author scholar
+ */
+@Mapper
+public interface CrmStatisticsPerformanceMapper {
+
+ /**
+ * 员工签约合同数量
+ *
+ * @param performanceReqVO 参数
+ * @return 员工签约合同数量
+ */
+ List selectContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+ /**
+ * 员工签约合同金额
+ *
+ * @param performanceReqVO 参数
+ * @return 员工签约合同金额
+ */
+ List selectContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+ /**
+ * 员工回款金额
+ *
+ * @param performanceReqVO 参数
+ * @return 员工回款金额
+ */
+ List selectReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java
index a7c9427..a7c9427 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsPortraitMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankMapper.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankMapper.java
index d58241c..d58241c 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankMapper.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/statistics/CrmStatisticsRankMapper.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java
index 2932c1d..2932c1d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/RedisKeyConstants.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
index e917b13..e917b13 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/redis/no/CrmNoRedisDAO.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
index eee2b32..eee2b32 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/DictTypeConstants.java
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/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
index 07a6dad..07a6dad 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
index aeeed31..aeeed31 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java
index e199a88..e199a88 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/business/CrmBusinessEndStatusEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java
index 3203481..3203481 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmAuditStatusEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
index f2d3aaa..f2d3aaa 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java
index 9a1a420..9a1a420 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java
index 4440275..4440275 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
index 7fd5eb3..7fd5eb3 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java
index 85ab1bb..85ab1bb 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionLevelEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/product/CrmProductStatusEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/product/CrmProductStatusEnum.java
index f940e88..f940e88 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/product/CrmProductStatusEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/product/CrmProductStatusEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java
index e10385a..e10385a 100644
--- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/receivable/CrmReceivableReturnTypeEnum.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunction.java
index 8f0a889..8f0a889 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/core/AreaExcelColumnSelectFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/package-info.java
index c2deef8..c2deef8 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/excel/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java
index d8bb509..d8bb509 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBusinessParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java
index 91e8fd2..91e8fd2 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java
index d3c5852..d3c5852 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerIndustryParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerIndustryParseFunction.java
index 4be92e0..4be92e0 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerIndustryParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerIndustryParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerLevelParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerLevelParseFunction.java
index 69cc301..69cc301 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerLevelParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerLevelParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java
index a58c045..a58c045 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerSourceParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerSourceParseFunction.java
index b6ac601..b6ac601 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerSourceParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerSourceParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductStatusParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductStatusParseFunction.java
index 8034e11..8034e11 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductStatusParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductStatusParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductUnitParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductUnitParseFunction.java
index c769489..c769489 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductUnitParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmProductUnitParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java
index b43074a..b43074a 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivablePlanParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java
index e2a868f..e2a868f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmReceivableReturnTypeParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAdminUserParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAdminUserParseFunction.java
index 05f96c5..05f96c5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAdminUserParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAdminUserParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAreaParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAreaParseFunction.java
index 3ccc769..3ccc769 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAreaParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysAreaParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysBooleanParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysBooleanParseFunction.java
index 16d24e1..16d24e1 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysBooleanParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysBooleanParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysDeptParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysDeptParseFunction.java
index 6d01f9f..6d01f9f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysDeptParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysDeptParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysSexParseFunction.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysSexParseFunction.java
index 4678fdd..4678fdd 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysSexParseFunction.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/SysSexParseFunction.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java
index 413b652..413b652 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java
index 281e36c..281e36c 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java
index 9ef6d4d..9ef6d4d 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
index d490258..d490258 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java
index d895fe9..d895fe9 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java
index 97f76db..97f76db 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/config/CrmWebConfiguration.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/web/config/CrmWebConfiguration.java
index 5b68d8e..5b68d8e 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/config/CrmWebConfiguration.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/web/config/CrmWebConfiguration.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java
index 5c4e249..09de726 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/api/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java
@@ -1,4 +1,4 @@
/**
- * crm API 实现类,定义暴露给其它模块的 API
+ * crm 模块的 web 拓展封装
*/
-package cn.iocoder.yudao.module.crm.api;
+package cn.iocoder.yudao.module.crm.framework.web;
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java
index 6f58170..6f58170 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
new file mode 100644
index 0000000..2214e6b
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 定时任务
+ */
+package cn.iocoder.yudao.module.crm.job;
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/package-info.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/package-info.java
index 2ea5f9f..2ea5f9f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/package-info.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/package-info.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
index abe5a70..abe5a70 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
index 2da3eb1..2da3eb1 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
new file mode 100644
index 0000000..bd9c164
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
@@ -0,0 +1,135 @@
+package cn.iocoder.yudao.module.crm.service.business;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * 商机状态 Service 接口
+ *
+ * @author ljlleo
+ */
+public interface CrmBusinessStatusService {
+
+ /**
+ * 创建商机状态
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createBusinessStatus(@Valid CrmBusinessStatusSaveReqVO createReqVO);
+
+ /**
+ * 更新商机状态
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateBusinessStatus(@Valid CrmBusinessStatusSaveReqVO updateReqVO);
+
+ /**
+ * 删除商机状态
+ *
+ * @param id 编号
+ */
+ void deleteBusinessStatusType(Long id);
+
+ /**
+ * 获得商机状态组
+ *
+ * @param id 编号
+ * @return 商机状态组
+ */
+ CrmBusinessStatusTypeDO getBusinessStatusType(Long id);
+
+ /**
+ * 校验商机状态组
+ *
+ * @param id 编号
+ */
+ void validateBusinessStatusType(Long id);
+
+ /**
+ * 获得商机状态组列表
+ *
+ * @return 商机状态组列表
+ */
+ List getBusinessStatusTypeList();
+
+ /**
+ * 获得商机状态组分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 商机状态组分页
+ */
+ PageResult getBusinessStatusTypePage(PageParam pageReqVO);
+
+ /**
+ * 获得商机状态组列表
+ *
+ * @param ids 编号数组
+ * @return 商机状态组列表
+ */
+ List getBusinessStatusTypeList(Collection ids);
+
+ /**
+ * 获得商机状态组 Map
+ *
+ * @param ids 编号数组
+ * @return 商机状态组 Map
+ */
+ default Map getBusinessStatusTypeMap(Collection ids) {
+ return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId);
+ }
+
+ /**
+ * 获得指定类型的商机状态列表
+ *
+ * @param typeId 商机状态组编号
+ * @return 商机状态列表
+ */
+ List getBusinessStatusListByTypeId(Long typeId);
+
+ /**
+ * 获得商机状态列表
+ *
+ * @param ids 编号数组
+ * @return 商机状态列表
+ */
+ List getBusinessStatusList(Collection ids);
+
+ /**
+ * 获得商机状态 Map
+ *
+ * @param ids 编号数组
+ * @return 商机状态 Map
+ */
+ default Map getBusinessStatusMap(Collection ids) {
+ return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId);
+ }
+
+ /**
+ * 获得商机状态
+ *
+ * @param id 编号
+ * @return 商机状态
+ */
+ CrmBusinessStatusDO getBusinessStatus(Long id);
+
+ /**
+ * 校验商机状态
+ *
+ * @param statusTypeId 商机状态组编号
+ * @param statusId 商机状态编号
+ */
+ CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java
index 2ec7766..2ec7766 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
new file mode 100644
index 0000000..26d0836
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
@@ -0,0 +1,91 @@
+package cn.iocoder.yudao.module.crm.service.clue;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
+import jakarta.validation.Valid;
+
+import java.time.LocalDateTime;
+
+/**
+ * 线索 Service 接口
+ *
+ * @author Wanwan
+ */
+public interface CrmClueService {
+
+ /**
+ * 创建线索
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createClue(@Valid CrmClueSaveReqVO createReqVO);
+
+ /**
+ * 更新线索
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateClue(@Valid CrmClueSaveReqVO updateReqVO);
+
+ /**
+ * 更新线索相关的跟进信息
+ *
+ * @param id 编号
+ * @param contactNextTime 下次联系时间
+ * @param contactLastContent 最后联系内容
+ */
+ void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
+
+ /**
+ * 删除线索
+ *
+ * @param id 编号
+ */
+ void deleteClue(Long id);
+
+ /**
+ * 获得线索
+ *
+ * @param id 编号
+ * @return 线索
+ */
+ CrmClueDO getClue(Long id);
+
+ /**
+ * 获得线索分页
+ *
+ * @param pageReqVO 分页查询
+ * @param userId 用户编号
+ * @return 线索分页
+ */
+ PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId);
+
+ /**
+ * 线索转移
+ *
+ * @param reqVO 请求
+ * @param userId 用户编号
+ */
+ void transferClue(CrmClueTransferReqVO reqVO, Long userId);
+
+ /**
+ * 线索转化为客户
+ *
+ * @param id 线索编号
+ * @param userId 用户编号
+ */
+ void transformClue(Long id, Long userId);
+
+ /**
+ * 获得分配给我的、待跟进的线索数量
+ *
+ * @param userId 用户编号
+ * @return 数量
+ */
+ Long getFollowClueCount(Long userId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
index c8c850a..c8c850a 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
new file mode 100644
index 0000000..2deaf00
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.crm.service.contact;
+
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusiness2ReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * CRM 联系人与商机的关联 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface CrmContactBusinessService {
+
+ /**
+ * 创建联系人与商机的关联【通过联系人,关联商机】
+ *
+ * @param createReqVO 创建信息
+ */
+ void createContactBusinessList(@Valid CrmContactBusinessReqVO createReqVO);
+
+ /**
+ * 创建联系人与商机的关联【通过商机,关联联系人】
+ *
+ * @param createReqVO 创建信息
+ */
+ void createContactBusinessList2(@Valid CrmContactBusiness2ReqVO createReqVO);
+
+ /**
+ * 删除联系人与商机的关联【通过联系人,取关商机】
+ *
+ * @param deleteReqVO 删除信息
+ */
+ void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
+
+ /**
+ * 删除联系人与商机的关联【通过商机,取关联系人】
+ *
+ * @param deleteReqVO 删除信息
+ */
+ void deleteContactBusinessList2(@Valid CrmContactBusiness2ReqVO deleteReqVO);
+
+ /**
+ * 删除联系人与商机的关联,基于联系人编号
+ *
+ * @param contactId 联系人编号
+ */
+ void deleteContactBusinessByContactId(Long contactId);
+
+ /**
+ * 获得联系人与商机的关联列表,基于联系人编号
+ *
+ * @param contactId 联系人编号
+ * @return 联系人商机关联
+ */
+ List getContactBusinessListByContactId(Long contactId);
+
+ /**
+ * 获得联系人与商机的关联列表,基于商机编号
+ *
+ * @param businessId 商机编号
+ * @return 联系人商机关联
+ */
+ List getContactBusinessListByBusinessId(Long businessId);
+
+}
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
index c8850e3..c8850e3 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
new file mode 100644
index 0000000..971d413
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
@@ -0,0 +1,172 @@
+package cn.iocoder.yudao.module.crm.service.contact;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import jakarta.validation.Valid;
+
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 联系人 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface CrmContactService {
+
+ /**
+ * 创建联系人
+ *
+ * @param createReqVO 创建信息
+ * @param userId 用户编号
+ * @return 编号
+ */
+ Long createContact(@Valid CrmContactSaveReqVO createReqVO, Long userId);
+
+ /**
+ * 更新联系人
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateContact(@Valid CrmContactSaveReqVO updateReqVO);
+
+ /**
+ * 删除联系人
+ *
+ * @param id 编号
+ */
+ void deleteContact(Long id);
+
+ /**
+ * 联系人转移
+ *
+ * @param reqVO 请求
+ * @param userId 用户编号
+ */
+ void transferContact(CrmContactTransferReqVO reqVO, Long userId);
+
+ /**
+ * 更新指定客户的联系人的负责人
+ * 数据权限基于 【客户】
+ *
+ * @param customerId 客户编号
+ * @param ownerUserId 用户编号
+ */
+ void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId);
+
+ /**
+ * 更新联系人相关跟进信息
+ *
+ * @param id 编号
+ * @param contactNextTime 下次联系时间
+ * @param contactLastContent 最后联系内容
+ */
+ void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
+
+ /**
+ * 更新联系人的下次联系时间
+ *
+ * @param ids 编号数组
+ * @param contactNextTime 下次联系时间
+ */
+ void updateContactContactNextTime(Collection ids, LocalDateTime contactNextTime);
+
+ /**
+ * 获得联系人
+ *
+ * @param id 编号
+ * @return 联系人
+ */
+ CrmContactDO getContact(Long id);
+
+ /**
+ * 校验联系人
+ *
+ * @param id 编号
+ */
+ void validateContact(Long id);
+
+ /**
+ * 获得联系人列表
+ *
+ * @param ids 编号
+ * @return 联系人列表
+ */
+ List getContactList(Collection ids);
+
+ /**
+ * 获得联系人 Map
+ *
+ * @param ids 编号
+ * @return 联系人 Map
+ */
+ default Map getContactMap(Collection ids) {
+ return convertMap(getContactList(ids), CrmContactDO::getId);
+ }
+
+ /**
+ * 获取联系人列表(校验权限)
+ *
+ * @param userId 用户编号
+ * @return 联系人列表
+ */
+ List getContactList(Long userId);
+
+ /**
+ * 获得联系人分页
+ *
+ * 数据权限:基于 {@link CrmContactDO}
+ *
+ * @param pageReqVO 分页查询
+ * @param userId 用户编号
+ * @return 联系人分页
+ */
+ PageResult getContactPage(CrmContactPageReqVO pageReqVO, Long userId);
+
+ /**
+ * 获得联系人分页
+ *
+ * 数据权限:基于 {@link CrmCustomerDO}
+ *
+ * @param pageVO 分页查询
+ * @return 联系人分页
+ */
+ PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO);
+
+ /**
+ * 获得联系人分页
+ *
+ * 数据权限:基于 {@link CrmBusinessDO}
+ *
+ * @param pageVO 分页查询
+ * @return 联系人分页
+ */
+ PageResult getContactPageByBusinessId(CrmContactPageReqVO pageVO);
+
+ /**
+ * 获取关联客户的联系人数量
+ *
+ * @param customerId 客户编号
+ * @return 数量
+ */
+ Long getContactCountByCustomerId(Long customerId);
+
+ /**
+ * 获得联系人列表
+ *
+ * @param customerId 客户编号
+ * @param ownerUserId 负责人编号
+ * @return 联系人列表
+ */
+ List getContactListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
index ebb5066..ebb5066 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java
index 79471aa..79471aa 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigService.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java
new file mode 100644
index 0000000..c9379dc
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.crm.service.contract;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO;
+import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractConfigMapper;
+import com.mzt.logapi.context.LogRecordContext;
+import com.mzt.logapi.starter.annotation.LogRecord;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Objects;
+
+import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
+
+/**
+ * 合同配置 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class CrmContractConfigServiceImpl implements CrmContractConfigService {
+
+ @Resource
+ private CrmContractConfigMapper contractConfigMapper;
+
+ @Override
+ public CrmContractConfigDO getContractConfig() {
+ return contractConfigMapper.selectOne();
+ }
+
+ @Override
+ @LogRecord(type = CRM_CONTRACT_CONFIG_TYPE, subType = CRM_CONTRACT_CONFIG_SUB_TYPE, bizNo = "{{#configId}}",
+ success = CRM_CONTRACT_CONFIG_SUCCESS)
+ public void saveContractConfig(CrmContractConfigSaveReqVO saveReqVO) {
+ // 1. 存在,则进行更新
+ CrmContractConfigDO dbConfig = getContractConfig();
+ CrmContractConfigDO config = BeanUtils.toBean(saveReqVO, CrmContractConfigDO.class);
+ if (Objects.nonNull(dbConfig)) {
+ contractConfigMapper.updateById(config.setId(dbConfig.getId()));
+ // 记录操作日志上下文
+ LogRecordContext.putVariable("isConfigUpdate", Boolean.TRUE);
+ LogRecordContext.putVariable("configId", config.getId());
+ return;
+ }
+
+ // 2. 不存在,则进行插入
+ contractConfigMapper.insert(config);
+ // 记录操作日志上下文
+ LogRecordContext.putVariable("isConfigUpdate", Boolean.FALSE);
+ LogRecordContext.putVariable("configId", config.getId());
+ }
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
index 0d8964f..0d8964f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
index 7625261..7625261 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java
new file mode 100644
index 0000000..ce82858
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.crm.service.contract.listener;
+
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener;
+import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
+import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Component;
+
+/**
+ * 合同审批的结果的监听器实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+public class CrmContractStatusListener extends BpmProcessInstanceStatusEventListener {
+
+ @Resource
+ private CrmContractService contractService;
+
+ @Override
+ public String getProcessDefinitionKey() {
+ return CrmContractServiceImpl.BPM_PROCESS_DEFINITION_KEY;
+ }
+
+ @Override
+ protected void onEvent(BpmProcessInstanceStatusEvent event) {
+ contractService.updateContractAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
new file mode 100644
index 0000000..f67f377
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
@@ -0,0 +1,64 @@
+package cn.iocoder.yudao.module.crm.service.customer;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 客户限制配置 Service 接口
+ *
+ * @author Wanwan
+ */
+public interface CrmCustomerLimitConfigService {
+
+ /**
+ * 创建客户限制配置
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO createReqVO);
+
+ /**
+ * 更新客户限制配置
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO updateReqVO);
+
+ /**
+ * 删除客户限制配置
+ *
+ * @param id 编号
+ */
+ void deleteCustomerLimitConfig(Long id);
+
+ /**
+ * 获得客户限制配置
+ *
+ * @param id 编号
+ * @return 客户限制配置
+ */
+ CrmCustomerLimitConfigDO getCustomerLimitConfig(Long id);
+
+ /**
+ * 获得客户限制配置分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 客户限制配置分页
+ */
+ PageResult getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO);
+
+ /**
+ * 查询用户对应的配置列表
+ *
+ * @param type 类型
+ * @param userId 用户类型
+ */
+ List getCustomerLimitConfigListByUserId(Integer type, Long userId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java
index 6d6a49f..6d6a49f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigService.java
index 30eb6f5..30eb6f5 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigService.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java
new file mode 100644
index 0000000..9099b19
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.crm.service.customer;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
+import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerPoolConfigMapper;
+import com.mzt.logapi.context.LogRecordContext;
+import com.mzt.logapi.starter.annotation.LogRecord;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Objects;
+
+import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
+
+/**
+ * 客户公海配置 Service 实现类
+ *
+ * @author Wanwan
+ */
+@Service
+@Validated
+public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigService {
+
+ @Resource
+ private CrmCustomerPoolConfigMapper customerPoolConfigMapper;
+
+ @Override
+ public CrmCustomerPoolConfigDO getCustomerPoolConfig() {
+ return customerPoolConfigMapper.selectOne();
+ }
+
+ @Override
+ @LogRecord(type = CRM_CUSTOMER_POOL_CONFIG_TYPE, subType = CRM_CUSTOMER_POOL_CONFIG_SUB_TYPE, bizNo = "{{#poolConfigId}}",
+ success = CRM_CUSTOMER_POOL_CONFIG_SUCCESS)
+ public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) {
+ // 1. 存在,则进行更新
+ CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig();
+ CrmCustomerPoolConfigDO poolConfig = BeanUtils.toBean(saveReqVO, CrmCustomerPoolConfigDO.class);
+ if (Objects.nonNull(dbConfig)) {
+ customerPoolConfigMapper.updateById(poolConfig.setId(dbConfig.getId()));
+ // 记录操作日志上下文
+ LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.TRUE);
+ LogRecordContext.putVariable("poolConfigId", poolConfig.getId());
+ return;
+ }
+
+ // 2. 不存在,则进行插入
+ customerPoolConfigMapper.insert(poolConfig);
+ // 记录操作日志上下文
+ LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.FALSE);
+ LogRecordContext.putVariable("poolConfigId", poolConfig.getId());
+ }
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
index 971d413..70b4f9f 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -1,12 +1,9 @@
-package cn.iocoder.yudao.module.crm.service.contact;
+package cn.iocoder.yudao.module.crm.service.customer;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
@@ -17,156 +14,185 @@ import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
- * CRM 联系人 Service 接口
+ * 客户 Service 接口
*
- * @author 芋道源码
+ * @author Wanwan
*/
-public interface CrmContactService {
+public interface CrmCustomerService {
/**
- * 创建联系人
+ * 创建客户
*
* @param createReqVO 创建信息
* @param userId 用户编号
* @return 编号
*/
- Long createContact(@Valid CrmContactSaveReqVO createReqVO, Long userId);
+ Long createCustomer(@Valid CrmCustomerSaveReqVO createReqVO, Long userId);
/**
- * 更新联系人
+ * 更新客户
*
* @param updateReqVO 更新信息
*/
- void updateContact(@Valid CrmContactSaveReqVO updateReqVO);
+ void updateCustomer(@Valid CrmCustomerSaveReqVO updateReqVO);
/**
- * 删除联系人
+ * 更新客户的跟进状态
*
- * @param id 编号
+ * @param id 编号
+ * @param dealStatus 跟进状态
*/
- void deleteContact(Long id);
+ void updateCustomerDealStatus(Long id, Boolean dealStatus);
/**
- * 联系人转移
+ * 更新客户相关的跟进信息
*
- * @param reqVO 请求
- * @param userId 用户编号
+ * @param id 编号
+ * @param contactNextTime 下次联系时间
+ * @param contactLastContent 最后联系内容
*/
- void transferContact(CrmContactTransferReqVO reqVO, Long userId);
+ void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
/**
- * 更新指定客户的联系人的负责人
- * 数据权限基于 【客户】
+ * 删除客户
*
- * @param customerId 客户编号
- * @param ownerUserId 用户编号
+ * @param id 编号
*/
- void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId);
+ void deleteCustomer(Long id);
/**
- * 更新联系人相关跟进信息
+ * 获得客户
*
- * @param id 编号
- * @param contactNextTime 下次联系时间
- * @param contactLastContent 最后联系内容
+ * @param id 编号
+ * @return 客户
*/
- void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
+ CrmCustomerDO getCustomer(Long id);
/**
- * 更新联系人的下次联系时间
+ * 获得客户列表
*
- * @param ids 编号数组
- * @param contactNextTime 下次联系时间
+ * @param ids 客户编号数组
+ * @return 客户列表
+ * @author ljlleo
*/
- void updateContactContactNextTime(Collection ids, LocalDateTime contactNextTime);
+ List getCustomerList(Collection ids);
/**
- * 获得联系人
+ * 获得客户 Map
*
- * @param id 编号
- * @return 联系人
+ * @param ids 客户编号数组
+ * @return 客户 Map
*/
- CrmContactDO getContact(Long id);
+ default Map getCustomerMap(Collection ids) {
+ return convertMap(getCustomerList(ids), CrmCustomerDO::getId);
+ }
/**
- * 校验联系人
+ * 获得客户分页
*
- * @param id 编号
+ * @param pageReqVO 分页查询
+ * @param userId 用户编号
+ * @return 客户分页
*/
- void validateContact(Long id);
+ PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId);
/**
- * 获得联系人列表
+ * 获得放入公海提醒的客户分页
*
- * @param ids 编号
- * @return 联系人列表
+ * @param pageVO 分页查询
+ * @param userId 用户编号
+ * @return 客户分页
*/
- List getContactList(Collection ids);
+ PageResult getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId);
/**
- * 获得联系人 Map
+ * 获得待进入公海的客户数量
*
- * @param ids 编号
- * @return 联系人 Map
+ * @param userId 用户编号
+ * @return 提醒数量
*/
- default Map getContactMap(Collection ids) {
- return convertMap(getContactList(ids), CrmContactDO::getId);
- }
+ Long getPutPoolRemindCustomerCount(Long userId);
/**
- * 获取联系人列表(校验权限)
+ * 获得今日需联系客户数量
*
* @param userId 用户编号
- * @return 联系人列表
+ * @return 提醒数量
*/
- List getContactList(Long userId);
+ Long getTodayContactCustomerCount(Long userId);
/**
- * 获得联系人分页
+ * 获得分配给我的客户数量
*
- * 数据权限:基于 {@link CrmContactDO}
+ * @param userId 用户编号
+ * @return 提醒数量
+ */
+ Long getFollowCustomerCount(Long userId);
+
+ /**
+ * 校验客户是否存在
*
- * @param pageReqVO 分页查询
- * @param userId 用户编号
- * @return 联系人分页
+ * @param id 编号
*/
- PageResult getContactPage(CrmContactPageReqVO pageReqVO, Long userId);
+ void validateCustomer(Long id);
/**
- * 获得联系人分页
+ * 客户转移
*
- * 数据权限:基于 {@link CrmCustomerDO}
+ * @param reqVO 请求
+ * @param userId 用户编号
+ */
+ void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId);
+
+ /**
+ * 锁定/解锁客户
*
- * @param pageVO 分页查询
- * @return 联系人分页
+ * @param lockReqVO 更新信息
+ * @param userId 用户编号
*/
- PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO);
+ void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId);
/**
- * 获得联系人分页
+ * 创建客户
*
- * 数据权限:基于 {@link CrmBusinessDO}
+ * @param customerCreateReq 请求信息
+ * @param userId 用户编号
+ * @return 客户列表
+ */
+ Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId);
+
+ /**
+ * 批量导入客户
*
- * @param pageVO 分页查询
- * @return 联系人分页
+ * @param importCustomers 导入客户列表
+ * @param importReqVO 请求
+ * @return 导入结果
+ */
+ CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO);
+
+ // ==================== 公海相关操作 ====================
+
+ /**
+ * 客户放入公海
+ *
+ * @param id 客户编号
*/
- PageResult getContactPageByBusinessId(CrmContactPageReqVO pageVO);
+ void putCustomerPool(Long id);
/**
- * 获取关联客户的联系人数量
+ * 领取公海客户
*
- * @param customerId 客户编号
- * @return 数量
+ * @param ids 要领取的客户编号数组
+ * @param ownerUserId 负责人
+ * @param isReceive 是/否领取;true - 领取;false - 分配
*/
- Long getContactCountByCustomerId(Long customerId);
+ void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive);
/**
- * 获得联系人列表
+ * 【系统】客户自动掉入公海
*
- * @param customerId 客户编号
- * @param ownerUserId 负责人编号
- * @return 联系人列表
+ * @return 掉入公海数量
*/
- List getContactListByCustomerIdOwnerUserId(Long customerId, Long ownerUserId);
+ int autoPutCustomerPool();
}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
index 75d3af0..75d3af0 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java
new file mode 100644
index 0000000..58d1476
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java
@@ -0,0 +1,121 @@
+package cn.iocoder.yudao.module.crm.service.customer.bo;
+
+import cn.iocoder.yudao.framework.common.validation.Mobile;
+import cn.iocoder.yudao.framework.common.validation.Telephone;
+import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 客户创建 Create Req BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CrmCustomerCreateReqBO {
+
+ /**
+ * 客户名称
+ */
+ @NotEmpty(message = "客户名称不能为空")
+ private String name;
+ /**
+ * 跟进状态
+ */
+ private Boolean followUpStatus;
+ /**
+ * 锁定状态
+ */
+ private Boolean lockStatus;
+ /**
+ * 成交状态
+ */
+ private Boolean dealStatus;
+ /**
+ * 所属行业
+ *
+ * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
+ */
+ private Integer industryId;
+ /**
+ * 客户等级
+ *
+ * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL}
+ */
+ private Integer level;
+ /**
+ * 客户来源
+ *
+ * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE}
+ */
+ private Integer source;
+
+ /**
+ * 手机
+ */
+ @Mobile
+ private String mobile;
+ /**
+ * 电话
+ */
+ @Telephone
+ private String telephone;
+ /**
+ * QQ
+ */
+ private String qq;
+ /**
+ * wechat
+ */
+ private String wechat;
+
+ /**
+ * 邮箱
+ */
+ @Email(message = "邮箱格式不正确")
+ private String email;
+
+ /**
+ * 客户描述
+ */
+ @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符")
+ private String description;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 负责人的用户编号
+ *
+ * 关联 AdminUserDO 的 id 字段
+ */
+ private Long ownerUserId;
+ /**
+ * 所在地
+ *
+ * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
+ */
+ private Integer areaId;
+ /**
+ * 详细地址
+ */
+ private String detailAddress;
+
+ /**
+ * 最后跟进时间
+ */
+ private LocalDateTime contactLastTime;
+ /**
+ * 最后跟进内容
+ */
+ private String contactLastContent;
+ /**
+ * 下次联系时间
+ */
+ private LocalDateTime contactNextTime;
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java
new file mode 100644
index 0000000..d2a7cb8
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java
@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.crm.service.followup;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO;
+import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 跟进记录 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface CrmFollowUpRecordService {
+
+ /**
+ * 创建跟进记录 (数据权限基于 bizType、 bizId)
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createFollowUpRecord(@Valid CrmFollowUpRecordSaveReqVO createReqVO);
+
+ /**
+ * 创建更进
+ *
+ * @param list 请求
+ */
+ void createFollowUpRecordBatch(List list);
+
+ /**
+ * 删除跟进记录 (数据权限基于 bizType、 bizId)
+ *
+ * @param id 编号
+ * @param userId 用户编号
+ */
+ void deleteFollowUpRecord(Long id, Long userId);
+
+ /**
+ * 删除跟进
+ *
+ * @param bizType 模块类型
+ * @param bizId 模块数据编号
+ */
+ void deleteFollowUpRecordByBiz(Integer bizType, Long bizId);
+
+ /**
+ * 获得跟进记录
+ *
+ * @param id 编号
+ * @return 跟进记录
+ */
+ CrmFollowUpRecordDO getFollowUpRecord(Long id);
+
+ /**
+ * 获得跟进记录分页 (数据权限基于 bizType、 bizId)
+ *
+ * @param pageReqVO 分页查询
+ * @return 跟进记录分页
+ */
+ PageResult getFollowUpRecordPage(CrmFollowUpRecordPageReqVO pageReqVO);
+
+ /**
+ * 获取跟进记录
+ *
+ * @param bizType 模块类型
+ * @param bizIds 模块数据编号
+ * @return 跟进列表
+ */
+ List getFollowUpRecordByBiz(Integer bizType, Collection bizIds);
+
+}
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
index 31c62d3..31c62d3 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java
new file mode 100644
index 0000000..dec219e
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java
@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.crm.service.followup.bo;
+
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 跟进信息 Create Req BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CrmFollowUpCreateReqBO {
+
+ /**
+ * 数据类型
+ *
+ * 枚举 {@link CrmBizTypeEnum}
+ */
+ @NotNull(message = "数据类型不能为空")
+ private Integer bizType;
+ /**
+ * 数据编号
+ *
+ * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段
+ */
+ @NotNull(message = "数据编号不能为空")
+ private Long bizId;
+
+ /**
+ * 跟进类型
+ *
+ * 关联 {@link DictTypeConstants#CRM_FOLLOW_UP_TYPE} 字典
+ */
+ @NotNull(message = "跟进类型不能为空")
+ private Integer type;
+ /**
+ * 跟进内容
+ */
+ @NotEmpty(message = "跟进内容不能为空")
+ private String content;
+ /**
+ * 下次联系时间
+ */
+ @NotNull(message = "下次联系时间不能为空")
+ private LocalDateTime nextTime;
+
+ /**
+ * 图片
+ */
+ private List picUrls;
+ /**
+ * 附件
+ */
+ private List fileUrls;
+
+ /**
+ * 关联的商机编号数组
+ *
+ * 关联 {@link CrmBusinessDO#getId()}
+ */
+ private List businessIds;
+
+ /**
+ * 关联的联系人编号数组
+ *
+ * 关联 {@link CrmContactDO#getId()}
+ */
+ private List contactIds;
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
new file mode 100644
index 0000000..2ff8113
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
@@ -0,0 +1,131 @@
+package cn.iocoder.yudao.module.crm.service.permission;
+
+
+import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionSaveReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * crm 数据权限 Service 接口
+ *
+ * @author HUIHUI
+ */
+public interface CrmPermissionService {
+
+ /**
+ * 创建数据权限
+ *
+ * @param reqVO 创建信息
+ * @param userId 用户编号
+ */
+ void createPermission(CrmPermissionSaveReqVO reqVO, Long userId);
+
+ /**
+ * 创建数据权限
+ *
+ * @param createReqBO 创建信息
+ * @return 编号
+ */
+ Long createPermission(@Valid CrmPermissionCreateReqBO createReqBO);
+
+ /**
+ * 创建数据权限
+ *
+ * @param createReqBOs 创建信息
+ */
+ void createPermissionBatch(@Valid List createReqBOs);
+
+ /**
+ * 更新数据权限
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updatePermission(CrmPermissionUpdateReqVO updateReqVO);
+
+ /**
+ * 数据权限转移
+ *
+ * @param crmPermissionTransferReqBO 数据权限转移请求
+ */
+ void transferPermission(@Valid CrmPermissionTransferReqBO crmPermissionTransferReqBO);
+
+ /**
+ * 删除数据权限
+ *
+ * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+ * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+ * @param level 数据权限级别,关联 {@link CrmPermissionLevelEnum}
+ */
+ void deletePermission(Integer bizType, Long bizId, Integer level);
+
+ /**
+ * 删除数据权限
+ *
+ * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+ * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+ */
+ void deletePermission(Integer bizType, Long bizId);
+
+ /**
+ * 批量删除数据权限
+ *
+ * @param ids 权限编号
+ * @param userId 用户编号
+ */
+ void deletePermissionBatch(Collection ids, Long userId);
+
+ /**
+ * 删除指定用户数据权限
+ *
+ * @param id 权限编号
+ * @param userId 用户编号
+ */
+ void deleteSelfPermission(Long id, Long userId);
+
+ /**
+ * 获取数据权限列表,通过 数据类型 x 某个数据
+ *
+ * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+ * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+ * @return Crm 数据权限列表
+ */
+ List getPermissionListByBiz(Integer bizType, Long bizId);
+
+ /**
+ * 获取数据权限列表,通过 数据类型 x 某个数据
+ *
+ * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+ * @param bizIds 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+ * @return Crm 数据权限列表
+ */
+ List getPermissionListByBiz(Integer bizType, Collection bizIds);
+
+ /**
+ * 获取用户参与的模块数据列表
+ *
+ * @param bizType 模块类型
+ * @param userId 用户编号
+ * @return 模块数据列表
+ */
+ List getPermissionListByBizTypeAndUserId(Integer bizType, Long userId);
+
+ /**
+ * 校验是否有指定数据的操作权限
+ *
+ * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
+ * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
+ * @param userId 用户编号
+ * @param level 权限级别
+ * @return 是否有权限
+ */
+ boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
index e6d1c5b..e6d1c5b 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java
new file mode 100644
index 0000000..f4b4bb3
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.crm.service.permission.bo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+
+/**
+ * crm 数据权限 Create Req BO
+ *
+ * @author HUIHUI
+ */
+@Data
+public class CrmPermissionCreateReqBO {
+
+ /**
+ * 当前登录用户编号
+ */
+ @NotNull(message = "用户编号不能为空")
+ private Long userId;
+
+ /**
+ * Crm 类型
+ */
+ @NotNull(message = "Crm 类型不能为空")
+ @InEnum(CrmBizTypeEnum.class)
+ private Integer bizType;
+ /**
+ * 数据编号
+ */
+ @NotNull(message = "Crm 数据编号不能为空")
+ private Long bizId;
+
+ /**
+ * 权限级别
+ */
+ @NotNull(message = "权限级别不能为空")
+ @InEnum(CrmPermissionLevelEnum.class)
+ private Integer level;
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java
new file mode 100644
index 0000000..52f8a97
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java
@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.crm.service.permission.bo;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.NoArgsConstructor;
+
+/**
+ * 数据权限转移 Request BO
+ *
+ * @author HUIHUI
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class CrmPermissionTransferReqBO {
+
+ /**
+ * 当前登录用户编号
+ */
+ @NotNull(message = "用户编号不能为空")
+ private Long userId;
+
+ /**
+ * CRM 类型
+ */
+ @NotNull(message = "Crm 类型不能为空")
+ @InEnum(CrmBizTypeEnum.class)
+ private Integer bizType;
+ /**
+ * 数据编号
+ */
+ @NotNull(message = "CRM 数据编号不能为空")
+ private Long bizId;
+
+ /**
+ * 新负责人的用户编号
+ */
+ @NotNull(message = "新负责人的用户编号不能为空")
+ private Long newOwnerUserId;
+
+ /**
+ * 老负责人加入团队后的权限级别。如果 null 说明移除
+ *
+ * 关联 {@link CrmPermissionLevelEnum}
+ */
+ private Integer oldOwnerPermissionLevel;
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java
new file mode 100644
index 0000000..c68c0cf
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.crm.service.product;
+
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 产品分类 Service 接口
+ *
+ * @author ZanGe丶
+ */
+public interface CrmProductCategoryService {
+
+ /**
+ * 创建产品分类
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createProductCategory(@Valid CrmProductCategoryCreateReqVO createReqVO);
+
+ /**
+ * 更新产品分类
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateProductCategory(@Valid CrmProductCategoryCreateReqVO updateReqVO);
+
+ /**
+ * 删除产品分类
+ *
+ * @param id 编号
+ */
+ void deleteProductCategory(Long id);
+
+ /**
+ * 获得产品分类
+ *
+ * @param id 编号
+ * @return 产品分类
+ */
+ CrmProductCategoryDO getProductCategory(Long id);
+
+ /**
+ * 获得产品分类列表
+ *
+ * @param listReqVO 列表请求
+ * @return 产品分类列表
+ */
+ List getProductCategoryList(CrmProductCategoryListReqVO listReqVO);
+
+ /**
+ * 获得产品分类列表
+ *
+ * @param ids 编号数组
+ * @return 产品分类列表
+ */
+ List getProductCategoryList(Collection ids);
+
+ /**
+ * 获得产品分类 Map
+ *
+ * @param ids 编号数组
+ * @return 产品分类 Map
+ */
+ default Map getProductCategoryMap(Collection ids) {
+ return convertMap(getProductCategoryList(ids), CrmProductCategoryDO::getId);
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
new file mode 100644
index 0000000..ce16888
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.crm.service.product;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
+import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductCategoryMapper;
+import com.mzt.logapi.context.LogRecordContext;
+import com.mzt.logapi.starter.annotation.LogRecord;
+import jakarta.annotation.Resource;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO.PARENT_ID_NULL;
+import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
+
+/**
+ * CRM 产品分类 Service 实现类
+ *
+ * @author ZanGe丶
+ */
+@Service
+@Validated
+public class CrmProductCategoryServiceImpl implements CrmProductCategoryService {
+
+ @Resource(name = "crmProductCategoryMapper")
+ private CrmProductCategoryMapper productCategoryMapper;
+
+ @Resource
+ @Lazy // 延迟加载,解决循环依赖问题
+ private CrmProductService crmProductService;
+
+ @Override
+ @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_CREATE_SUB_TYPE, bizNo = "{{#productCategoryId}}",
+ success = CRM_PRODUCT_CATEGORY_CREATE_SUCCESS)
+ public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) {
+ // 1.1 校验父分类存在
+ validateParentProductCategory(createReqVO.getParentId());
+ // 1.2 分类名称是否存在
+ validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName());
+
+ // 2. 插入分类
+ CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class);
+ productCategoryMapper.insert(category);
+
+ // 3. 记录操作日志上下文
+ LogRecordContext.putVariable("productCategoryId", category.getId());
+ return category.getId();
+ }
+
+ @Override
+ @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
+ success = CRM_PRODUCT_CATEGORY_UPDATE_SUCCESS)
+ public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) {
+ // 1.1 校验存在
+ validateProductCategoryExists(updateReqVO.getId());
+ // 1.2 校验父分类存在
+ validateParentProductCategory(updateReqVO.getParentId());
+ // 1.3 分类名称是否存在
+ validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
+
+ // 2. 更新分类
+ CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class);
+ productCategoryMapper.updateById(updateObj);
+ }
+
+ private void validateProductCategoryExists(Long id) {
+ if (productCategoryMapper.selectById(id) == null) {
+ throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
+ }
+ }
+
+ private void validateParentProductCategory(Long id) {
+ // 如果是根分类,无需验证
+ if (Objects.equals(id, PARENT_ID_NULL)) {
+ return;
+ }
+ // 父分类不存在
+ CrmProductCategoryDO category = productCategoryMapper.selectById(id);
+ if (category == null) {
+ throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS);
+ }
+ // 父分类不能是二级分类
+ if (!Objects.equals(category.getParentId(), PARENT_ID_NULL)) {
+ throw exception(PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL);
+ }
+ }
+
+ private void validateProductNameExists(Long id, Long parentId, String name) {
+ CrmProductCategoryDO category = productCategoryMapper.selectByParentIdAndName(parentId, name);
+ if (category == null
+ || category.getId().equals(id)) {
+ return;
+ }
+ throw exception(PRODUCT_CATEGORY_EXISTS);
+ }
+
+ @Override
+ @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_DELETE_SUB_TYPE, bizNo = "{{#id}}",
+ success = CRM_PRODUCT_CATEGORY_DELETE_SUCCESS)
+ public void deleteProductCategory(Long id) {
+ // 1.1 校验存在
+ validateProductCategoryExists(id);
+ // 1.2 校验是否还有子分类
+ if (productCategoryMapper.selectCountByParentId(id) > 0) {
+ throw exception(PRODUCT_CATEGORY_EXISTS_CHILDREN);
+ }
+ // 1.3 校验是否被产品使用
+ if (crmProductService.getProductByCategoryId(id) > 0) {
+ throw exception(PRODUCT_CATEGORY_USED);
+ }
+ // 2. 删除
+ productCategoryMapper.deleteById(id);
+ }
+
+ @Override
+ public CrmProductCategoryDO getProductCategory(Long id) {
+ return productCategoryMapper.selectById(id);
+ }
+
+ @Override
+ public List getProductCategoryList(CrmProductCategoryListReqVO listReqVO) {
+ return productCategoryMapper.selectList(listReqVO);
+ }
+
+ @Override
+ public List getProductCategoryList(Collection ids) {
+ return productCategoryMapper.selectBatchIds(ids);
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java
new file mode 100644
index 0000000..9379734
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java
@@ -0,0 +1,102 @@
+package cn.iocoder.yudao.module.crm.service.product;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 产品 Service 接口
+ *
+ * @author ZanGe丶
+ */
+public interface CrmProductService {
+
+ /**
+ * 创建产品
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createProduct(@Valid CrmProductSaveReqVO createReqVO);
+
+ /**
+ * 更新产品
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateProduct(@Valid CrmProductSaveReqVO updateReqVO);
+
+ /**
+ * 删除产品
+ *
+ * @param id 编号
+ */
+ void deleteProduct(Long id);
+
+ /**
+ * 获得产品
+ *
+ * @param id 编号
+ * @return 产品
+ */
+ CrmProductDO getProduct(Long id);
+
+ /**
+ * 获得产品列表
+ *
+ * @param ids 编号
+ * @return 产品列表
+ */
+ List getProductList(Collection ids);
+
+ /**
+ * 获得产品 Map
+ *
+ * @param ids 编号
+ * @return 产品 Map
+ */
+ default Map getProductMap(Collection ids) {
+ return convertMap(getProductList(ids), CrmProductDO::getId);
+ }
+
+ /**
+ * 获得产品分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 产品分页
+ */
+ PageResult getProductPage(CrmProductPageReqVO pageReqVO);
+
+ /**
+ * 获得产品数量
+ *
+ * @param categoryId 分类编号
+ * @return 产品
+ */
+ Long getProductByCategoryId(Long categoryId);
+
+ /**
+ * 获得指定状态的产品列表
+ *
+ * @param status 状态
+ * @return 产品列表
+ */
+ List getProductListByStatus(Integer status);
+
+ /**
+ * 校验产品们的有效性
+ *
+ * @param ids 编号数组
+ * @return 产品列表
+ */
+ List validProductList(Collection ids);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
index 0598e62..0598e62 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
new file mode 100644
index 0000000..b5d3cc2
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.crm.service.receivable;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * CRM 回款计划 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface CrmReceivablePlanService {
+
+ /**
+ * 创建回款计划
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createReceivablePlan(@Valid CrmReceivablePlanSaveReqVO createReqVO);
+
+ /**
+ * 更新回款计划
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateReceivablePlan(@Valid CrmReceivablePlanSaveReqVO updateReqVO);
+
+ /**
+ * 更新回款计划关联的回款编号
+ *
+ * @param id 编号
+ * @param receivableId 回款编号
+ */
+ void updateReceivablePlanReceivableId(Long id, Long receivableId);
+
+ /**
+ * 删除回款计划
+ *
+ * @param id 编号
+ */
+ void deleteReceivablePlan(Long id);
+
+ /**
+ * 获得回款计划
+ *
+ * @param id 编号
+ * @return 回款计划
+ */
+ CrmReceivablePlanDO getReceivablePlan(Long id);
+
+ /**
+ * 获得回款计划列表
+ *
+ * @param ids 编号
+ * @return 回款计划列表
+ */
+ List getReceivablePlanList(Collection ids);
+
+ /**
+ * 获得回款计划分页
+ *
+ * 数据权限:基于 {@link CrmReceivablePlanDO} 读取
+ *
+ * @param pageReqVO 分页查询
+ * @param userId 用户编号
+ * @return 回款计划分页
+ */
+ PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId);
+
+ /**
+ * 获得回款计划分页,基于指定客户
+ *
+ * 数据权限:基于 {@link CrmCustomerDO} 读取
+ *
+ * @param pageReqVO 分页查询
+ * @return 回款计划分页
+ */
+ PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
+
+ /**
+ * 获得待回款提醒数量
+ *
+ * @param userId 用户编号
+ * @return 提醒数量
+ */
+ Long getReceivablePlanRemindCount(Long userId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
index dd3de19..dd3de19 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
new file mode 100644
index 0000000..f6ac8c3
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
@@ -0,0 +1,133 @@
+package cn.iocoder.yudao.module.crm.service.receivable;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
+import jakarta.validation.Valid;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 回款 Service 接口
+ *
+ * @author 赤焰
+ */
+public interface CrmReceivableService {
+
+ /**
+ * 创建回款
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createReceivable(@Valid CrmReceivableSaveReqVO createReqVO);
+
+ /**
+ * 更新回款
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateReceivable(@Valid CrmReceivableSaveReqVO updateReqVO);
+
+ /**
+ * 更新回款流程审批结果
+ *
+ * @param id 回款编号
+ * @param bpmResult BPM 审批结果
+ */
+ void updateReceivableAuditStatus(Long id, Integer bpmResult);
+
+ /**
+ * 删除回款
+ *
+ * @param id 编号
+ */
+ void deleteReceivable(Long id);
+
+ /**
+ * 发起回款审批流程
+ *
+ * @param id 回款编号
+ * @param userId 用户编号
+ */
+ void submitReceivable(Long id, Long userId);
+
+ /**
+ * 获得回款
+ *
+ * @param id 编号
+ * @return 回款
+ */
+ CrmReceivableDO getReceivable(Long id);
+
+ /**
+ * 获得回款列表
+ *
+ * @param ids 编号
+ * @return 回款列表
+ */
+ List getReceivableList(Collection ids);
+
+ /**
+ * 获得回款 Map
+ *
+ * @param ids 编号
+ * @return 回款 Map
+ */
+ default Map getReceivableMap(Collection ids) {
+ return convertMap(getReceivableList(ids), CrmReceivableDO::getId);
+ }
+
+ /**
+ * 获得回款分页
+ *
+ * 数据权限:基于 {@link CrmReceivableDO} 读取
+ *
+ * @param pageReqVO 分页查询
+ * @param userId 用户编号
+ * @return 回款分页
+ */
+ PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId);
+
+ /**
+ * 获得回款分页,基于指定客户
+ *
+ * 数据权限:基于 {@link CrmCustomerDO} 读取
+ *
+ * @param pageReqVO 分页查询
+ * @return 回款分页
+ */
+ PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO);
+
+ /**
+ * 获得待审核回款数量
+ *
+ * @param userId 用户编号
+ * @return 待审批数量
+ */
+ Long getAuditReceivableCount(Long userId);
+
+ /**
+ * 获得合同已回款金额 Map
+ *
+ * @param contractIds 合同编号
+ * @return 回款金额 Map
+ */
+ Map getReceivablePriceMapByContractId(Collection contractIds);
+
+ /**
+ * 根据合同编号查询回款数量
+ *
+ * @param contractId 合同编号
+ * @return 回款数量
+ */
+ Long getReceivableCountByContractId(Long contractId);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
index 94e1bfb..94e1bfb 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
new file mode 100644
index 0000000..f0ddd86
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.crm.service.receivable.listener;
+
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener;
+import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService;
+import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Component;
+
+/**
+ * 回款审批的结果的监听器实现类
+ *
+ * @author HUIHUI
+ */
+@Component
+public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener {
+
+ @Resource
+ private CrmReceivableService receivableService;
+
+ @Override
+ public String getProcessDefinitionKey() {
+ return CrmReceivableServiceImpl.BPM_PROCESS_DEFINITION_KEY;
+ }
+
+ @Override
+ public void onEvent(BpmProcessInstanceStatusEvent event) {
+ receivableService.updateReceivableAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java
new file mode 100644
index 0000000..70c720b
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java
@@ -0,0 +1,112 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
+
+import java.util.List;
+
+/**
+ * CRM 客户分析 Service 接口
+ *
+ * @author dhb52
+ */
+public interface CrmStatisticsCustomerService {
+
+ /**
+ * 总量分析(按日期)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 总量分析(按用户)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 跟进次数分析(按日期)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 跟进次数分析(按用户)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 客户跟进次数分析(按类型)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 获取客户的首次合同、回款信息列表,用于【客户转化率】页面
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getContractSummary(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 公海客户分析(按日期)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getPoolSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 公海客户分析(按用户)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getPoolSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 客户成交周期(按日期)
+ *
+ * 成交周期的定义:客户 customer 在创建出来,到合同 contract 第一次成交的时间差
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerDealCycleByDate(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 客户成交周期(按用户)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 客户成交周期(按区域)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerDealCycleByArea(CrmStatisticsCustomerReqVO reqVO);
+
+ /**
+ * 客户成交周期(按产品)
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerDealCycleByProduct(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/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
index 1df4d5a..1df4d5a 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/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java
new file mode 100644
index 0000000..10458da
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.*;
+import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
+
+import java.util.List;
+
+/**
+ * CRM 销售漏斗分析 Service
+ *
+ * @author HUIHUI
+ */
+public interface CrmStatisticsFunnelService {
+
+ /**
+ * 获得销售漏斗数据
+ *
+ * @param reqVO 请求
+ * @return 销售漏斗数据
+ */
+ CrmStatisticFunnelSummaryRespVO getFunnelSummary(CrmStatisticsFunnelReqVO reqVO);
+
+ /**
+ * 获得商机结束状态统计
+ *
+ * @param reqVO 请求
+ * @return 商机结束状态统计
+ */
+ List getBusinessSummaryByEndStatus(CrmStatisticsFunnelReqVO reqVO);
+
+ /**
+ * 获取新增商机分析(按日期)
+ *
+ * @param reqVO 请求
+ * @return 新增商机分析
+ */
+ List getBusinessSummaryByDate(CrmStatisticsFunnelReqVO reqVO);
+
+ /**
+ * 获得商机转化率分析(按日期)
+ *
+ * @param reqVO 请求
+ * @return 商机转化率分析
+ */
+ List getBusinessInversionRateSummaryByDate(CrmStatisticsFunnelReqVO reqVO);
+
+ /**
+ * 获得商机分页(按日期)
+ *
+ * @param pageVO 请求
+ * @return 商机分页
+ */
+ PageResult getBusinessPageByDate(CrmStatisticsFunnelReqVO pageVO);
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java
index f4a04ed..f4a04ed 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelServiceImpl.java
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceService.java
new file mode 100644
index 0000000..15423af
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceService.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+
+import java.util.List;
+
+/**
+ * CRM 员工绩效统计 Service 接口
+ *
+ * @author scholar
+ */
+public interface CrmStatisticsPerformanceService {
+
+ /**
+ * 员工签约合同数量分析
+ *
+ * @param performanceReqVO 排行参数
+ * @return 员工签约合同数量排行分析
+ */
+ List getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+ /**
+ * 员工签约合同金额分析
+ *
+ * @param performanceReqVO 排行参数
+ * @return 员工签约合同金额分析
+ */
+ List getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+ /**
+ * 员工获得回款金额分析
+ *
+ * @param performanceReqVO 排行参数
+ * @return 员工获得回款金额分析
+ */
+ List getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO);
+
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java
new file mode 100644
index 0000000..719813e
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPerformanceServiceImpl.java
@@ -0,0 +1,120 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceRespVO;
+import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPerformanceMapper;
+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.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 员工业绩分析 Service 实现类
+ *
+ * @author scholar
+ */
+@Service
+@Validated
+public class CrmStatisticsPerformanceServiceImpl implements CrmStatisticsPerformanceService {
+
+ @Resource
+ private CrmStatisticsPerformanceMapper performanceMapper;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public List getContractCountPerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+ return getPerformance(performanceReqVO, performanceMapper::selectContractCountPerformance);
+ }
+
+ @Override
+ public List getContractPricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+ return getPerformance(performanceReqVO, performanceMapper::selectContractPricePerformance);
+ }
+
+ @Override
+ public List getReceivablePricePerformance(CrmStatisticsPerformanceReqVO performanceReqVO) {
+ return getPerformance(performanceReqVO, performanceMapper::selectReceivablePricePerformance);
+ }
+
+ /**
+ * 获得员工业绩数据
+ *
+ * 1. 获得今年 + 去年的数据
+ * 2. 遍历今年的月份,逐个拼接去年的月份数据
+ *
+ * @param performanceReqVO 参数
+ * @param performanceFunction 员工业绩统计方法
+ * @return 员工业绩数据
+ */
+ private List getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO,
+ Function> performanceFunction) {
+
+ // 1. 获得用户编号数组
+ List userIds = getUserIds(performanceReqVO);
+ if (CollUtil.isEmpty(userIds)) {
+ return Collections.emptyList();
+ }
+ performanceReqVO.setUserIds(userIds);
+
+ // 2. 获得业绩数据
+ int year = performanceReqVO.getTimes()[0].getYear(); // 获取查询的年份
+ performanceReqVO.getTimes()[0] = performanceReqVO.getTimes()[0].minusYears(1);
+ List performanceList = performanceFunction.apply(performanceReqVO);
+ Map performanceMap = convertMap(performanceList, CrmStatisticsPerformanceRespVO::getTime,
+ CrmStatisticsPerformanceRespVO::getCurrentMonthCount);
+
+ // 3. 组装数据返回
+ List result = new ArrayList<>();
+ for (int month = 1; month <= 12; month++) {
+ String currentMonth = String.format("%d%02d", year, month);
+ String lastMonth = month == 1 ? String.format("%d%02d", year - 1, 12) : String.format("%d%02d", year, month - 1);
+ String lastYear = String.format("%d%02d", year - 1, month);
+ result.add(new CrmStatisticsPerformanceRespVO().setTime(currentMonth)
+ .setCurrentMonthCount(performanceMap.getOrDefault(currentMonth, BigDecimal.ZERO))
+ .setLastMonthCount(performanceMap.getOrDefault(lastMonth, BigDecimal.ZERO))
+ .setLastYearCount(performanceMap.getOrDefault(lastYear, BigDecimal.ZERO)));
+ }
+ return result;
+ }
+
+ /**
+ * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组,包括子部门的所有用户编号
+ *
+ * @param reqVO 请求参数
+ * @return 用户编号数组
+ */
+ private List getUserIds(CrmStatisticsPerformanceReqVO reqVO) {
+ // 情况一:选中某个用户
+ if (ObjUtil.isNotNull(reqVO.getUserId())) {
+ return ListUtil.of(reqVO.getUserId());
+ }
+ // 情况二:选中某个部门
+ // 2.1 获得部门列表
+ final Long deptId = reqVO.getDeptId();
+ List deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
+ deptIds.add(deptId);
+ // 2.2 获得用户编号
+ return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitService.java
new file mode 100644
index 0000000..c568d3b
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitService.java
@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.*;
+
+import java.util.List;
+
+/**
+ * CRM 客户画像 Service 接口
+ *
+ * @author HUIHUI
+ */
+public interface CrmStatisticsPortraitService {
+
+ /**
+ * 获取客户地区统计数据
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryByArea(CrmStatisticsPortraitReqVO reqVO);
+
+ /**
+ * 获取客户行业统计数据
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryByIndustry(CrmStatisticsPortraitReqVO reqVO);
+
+ /**
+ * 获取客户级别统计数据
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryByLevel(CrmStatisticsPortraitReqVO reqVO);
+
+ /**
+ * 获取客户来源统计数据
+ *
+ * @param reqVO 请求参数
+ * @return 统计数据
+ */
+ List getCustomerSummaryBySource(CrmStatisticsPortraitReqVO reqVO);
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitServiceImpl.java
new file mode 100644
index 0000000..913ffb0
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsPortraitServiceImpl.java
@@ -0,0 +1,131 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.collection.ListUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.ip.core.Area;
+import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
+import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.portrait.*;
+import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsPortraitMapper;
+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.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+
+/**
+ * CRM 客户画像 Service 实现类
+ *
+ * @author HUIHUI
+ */
+@Service
+public class CrmStatisticsPortraitServiceImpl implements CrmStatisticsPortraitService {
+
+ @Resource
+ private CrmStatisticsPortraitMapper portraitMapper;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public List getCustomerSummaryByArea(CrmStatisticsPortraitReqVO reqVO) {
+ // 1. 获得用户编号数组
+ List userIds = getUserIds(reqVO);
+ if (CollUtil.isEmpty(userIds)) {
+ return Collections.emptyList();
+ }
+ reqVO.setUserIds(userIds);
+
+ // 2. 获取客户地区统计数据
+ List list = portraitMapper.selectSummaryListGroupByAreaId(reqVO);
+ if (CollUtil.isEmpty(list)) {
+ return Collections.emptyList();
+ }
+
+ // 3. 拼接数据
+ List areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
+ Map areaMap = convertMap(areaList, Area::getId);
+ return convertList(list, item -> {
+ Integer parentId = AreaUtils.getParentIdByType(item.getAreaId(), AreaTypeEnum.PROVINCE);
+ if (parentId != null) {
+ Area area = areaMap.get(parentId);
+ if (area != null) {
+ item.setAreaId(parentId).setAreaName(area.getName());
+ return item;
+ }
+ }
+ // 找不到,归到未知
+ return item.setAreaId(null).setAreaName("未知");
+ });
+ }
+
+ @Override
+ public List getCustomerSummaryByIndustry(CrmStatisticsPortraitReqVO reqVO) {
+ // 1. 获得用户编号数组
+ List userIds = getUserIds(reqVO);
+ if (CollUtil.isEmpty(userIds)) {
+ return Collections.emptyList();
+ }
+ reqVO.setUserIds(userIds);
+
+ // 2. 获取客户行业统计数据
+ return portraitMapper.selectCustomerIndustryListGroupByIndustryId(reqVO);
+ }
+
+ @Override
+ public List getCustomerSummaryBySource(CrmStatisticsPortraitReqVO reqVO) {
+ // 1. 获得用户编号数组
+ List userIds = getUserIds(reqVO);
+ if (CollUtil.isEmpty(userIds)) {
+ return Collections.emptyList();
+ }
+ reqVO.setUserIds(userIds);
+
+ // 2. 获取客户行业统计数据
+ return portraitMapper.selectCustomerSourceListGroupBySource(reqVO);
+ }
+
+ @Override
+ public List getCustomerSummaryByLevel(CrmStatisticsPortraitReqVO reqVO) {
+ // 1. 获得用户编号数组
+ List userIds = getUserIds(reqVO);
+ if (CollUtil.isEmpty(userIds)) {
+ return Collections.emptyList();
+ }
+ reqVO.setUserIds(userIds);
+
+ // 2. 获取客户级别统计数据
+ return portraitMapper.selectCustomerLevelListGroupByLevel(reqVO);
+ }
+
+ /**
+ * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组,包括子部门的所有用户编号
+ *
+ * @param reqVO 请求参数
+ * @return 用户编号数组
+ */
+ private List getUserIds(CrmStatisticsPortraitReqVO reqVO) {
+ // 情况一:选中某个用户
+ if (ObjUtil.isNotNull(reqVO.getUserId())) {
+ return ListUtil.of(reqVO.getUserId());
+ }
+ // 情况二:选中某个部门
+ // 2.1 获得部门列表
+ List deptIds = convertList(deptApi.getChildDeptList(reqVO.getDeptId()), DeptRespDTO::getId);
+ deptIds.add(reqVO.getDeptId());
+ // 2.2 获得用户编号
+ return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankService.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankService.java
new file mode 100644
index 0000000..2fc8a5b
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankService.java
@@ -0,0 +1,80 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.rank.CrmStatisticsRankRespVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.rank.CrmStatisticsRankReqVO;
+
+import java.util.List;
+
+/**
+ * CRM 排行榜统计 Service 接口
+ *
+ * @author anhaohao
+ */
+public interface CrmStatisticsRankService {
+
+ /**
+ * 获得合同金额排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 合同金额排行榜
+ */
+ List getContractPriceRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得回款金额排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 回款金额排行榜
+ */
+ List getReceivablePriceRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得签约合同数量排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 签约合同数量排行榜
+ */
+ List getContractCountRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得产品销量排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 产品销量排行榜
+ */
+ List getProductSalesRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得新增客户数排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 新增客户数排行榜
+ */
+ List getCustomerCountRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得联系人数量排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 联系人数量排行榜
+ */
+ List getContactsCountRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得跟进次数排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 跟进次数排行榜
+ */
+ List getFollowCountRank(CrmStatisticsRankReqVO rankReqVO);
+
+ /**
+ * 获得跟进客户数排行榜
+ *
+ * @param rankReqVO 排行参数
+ * @return 跟进客户数排行榜
+ */
+ List getFollowCustomerCountRank(CrmStatisticsRankReqVO rankReqVO);
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankServiceImpl.java
new file mode 100644
index 0000000..e591c35
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsRankServiceImpl.java
@@ -0,0 +1,134 @@
+package cn.iocoder.yudao.module.crm.service.statistics;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.rank.CrmStatisticsRankReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.rank.CrmStatisticsRankRespVO;
+import cn.iocoder.yudao.module.crm.dal.mysql.statistics.CrmStatisticsRankMapper;
+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.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+
+/**
+ * CRM 排行榜统计 Service 实现类
+ *
+ * @author anhaohao
+ */
+@Service
+@Validated
+public class CrmStatisticsRankServiceImpl implements CrmStatisticsRankService {
+
+ @Resource
+ private CrmStatisticsRankMapper rankMapper;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+ @Resource
+ private DeptApi deptApi;
+
+ @Override
+ public List getContractPriceRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectContractPriceRank);
+ }
+
+ @Override
+ public List getReceivablePriceRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectReceivablePriceRank);
+ }
+
+ @Override
+ public List getContractCountRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectContractCountRank);
+ }
+
+ @Override
+ public List getProductSalesRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectProductSalesRank);
+ }
+
+ @Override
+ public List getCustomerCountRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectCustomerCountRank);
+ }
+
+ @Override
+ public List getContactsCountRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectContactsCountRank);
+ }
+
+ @Override
+ public List getFollowCountRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectFollowCountRank);
+ }
+
+ @Override
+ public List getFollowCustomerCountRank(CrmStatisticsRankReqVO rankReqVO) {
+ return getRank(rankReqVO, rankMapper::selectFollowCustomerCountRank);
+ }
+
+ /**
+ * 获得排行版数据
+ *
+ * @param rankReqVO 参数
+ * @param rankFunction 排行榜方法
+ * @return 排行版数据
+ */
+ private List getRank(CrmStatisticsRankReqVO rankReqVO, Function> rankFunction) {
+ // 1. 获得用户编号数组
+ rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId()));
+ if (CollUtil.isEmpty(rankReqVO.getUserIds())) {
+ return Collections.emptyList();
+ }
+ // 2. 获得排行数据
+ List ranks = rankFunction.apply(rankReqVO);
+ if (CollUtil.isEmpty(ranks)) {
+ return Collections.emptyList();
+ }
+ ranks.sort(Comparator.comparing(CrmStatisticsRankRespVO::getCount).reversed());
+ // 3. 拼接用户信息
+ appendUserInfo(ranks);
+ return ranks;
+ }
+
+ /**
+ * 拼接用户信息(昵称、部门)
+ *
+ * @param ranks 排行榜数据
+ */
+ private void appendUserInfo(List ranks) {
+ Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmStatisticsRankRespVO::getOwnerUserId));
+ Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+ ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> {
+ rank.setNickname(user.getNickname());
+ MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> rank.setDeptName(dept.getName()));
+ }));
+ }
+
+ /**
+ * 获得部门下的用户编号数组,包括子部门的
+ *
+ * @param deptId 部门编号
+ * @return 用户编号数组
+ */
+ public List getUserIds(Long deptId) {
+ // 1. 获得部门列表
+ List deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
+ deptIds.add(deptId);
+ // 2. 获得用户编号
+ return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java
new file mode 100644
index 0000000..c1d4eaa
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmAuditStatusUtils.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.crm.util;
+
+import cn.hutool.core.lang.Assert;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
+
+/**
+ * CRM 流程工具类
+ *
+ * @author HUIHUI
+ */
+public class CrmAuditStatusUtils {
+
+ /**
+ * BPM 审批结果转换
+ *
+ * @param bpmResult BPM 审批结果
+ */
+ public static Integer convertBpmResultToAuditStatus(Integer bpmResult) {
+ Integer auditStatus = BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult) ? CrmAuditStatusEnum.APPROVE.getStatus()
+ : BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult) ? CrmAuditStatusEnum.REJECT.getStatus()
+ : BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult) ? BpmTaskStatusEnum.CANCEL.getStatus() : null;
+ Assert.notNull(auditStatus, "BPM 审批结果({}) 转换失败", bpmResult);
+ return auditStatus;
+ }
+
+}
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java
new file mode 100644
index 0000000..d2818cd
--- /dev/null
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java
@@ -0,0 +1,79 @@
+package cn.iocoder.yudao.module.crm.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
+import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
+import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
+import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+/**
+ * 数据权限工具类
+ *
+ * @author HUIHUI
+ */
+public class CrmPermissionUtils {
+
+ /**
+ * 校验用户是否是 CRM 管理员
+ *
+ * @return 是/否
+ */
+ public static boolean isCrmAdmin() {
+ PermissionApi permissionApi = SpringUtil.getBean(PermissionApi.class);
+ return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode());
+ }
+
+ /**
+ * 构造 CRM 数据类型数据【分页】查询条件
+ *
+ * @param query 连表查询对象
+ * @param bizType 数据类型 {@link CrmBizTypeEnum}
+ * @param bizId 数据编号
+ * @param userId 用户编号
+ * @param sceneType 场景类型
+ */
+ public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId,
+ Long userId, Integer sceneType) {
+ MybatisPlusJoinProperties mybatisPlusJoinProperties = SpringUtil.getBean(MybatisPlusJoinProperties.class);
+ final String ownerUserIdField = mybatisPlusJoinProperties.getTableAlias() + ".owner_user_id";
+ // 场景一:我负责的数据
+ if (CrmSceneTypeEnum.isOwner(sceneType)) {
+ query.eq(ownerUserIdField, userId);
+ }
+ // 场景二:我参与的数据(我有读或写权限,并且不是负责人)
+ if (CrmSceneTypeEnum.isInvolved(sceneType)) {
+ if (CrmPermissionUtils.isCrmAdmin()) { // 特殊逻辑:如果是超管,直接查询所有,不过滤数据权限
+ return;
+ }
+ query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType)
+ .eq(CrmPermissionDO::getBizId, bizId)
+ .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel())
+ .eq(CrmPermissionDO::getUserId,userId));
+ query.ne(ownerUserIdField, userId);
+ }
+ // 场景三:下属负责的数据(下属是负责人)
+ if (CrmSceneTypeEnum.isSubordinate(sceneType)) {
+ AdminUserApi adminUserApi = SpringUtil.getBean(AdminUserApi.class);
+ List subordinateUsers = adminUserApi.getUserListBySubordinate(userId);
+ if (CollUtil.isEmpty(subordinateUsers)) {
+ query.eq(ownerUserIdField, -1); // 不返回任何结果
+ } else {
+ query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId));
+ }
+ }
+ }
+
+}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
index dc10f12..dc10f12 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
+++ b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsCustomerMapper.xml
diff --git a/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml
new file mode 100644
index 0000000..a074062
--- /dev/null
+++ b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsFunnelMapper.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml
new file mode 100644
index 0000000..81962cd
--- /dev/null
+++ b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPerformanceMapper.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPortraitMapper.xml b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPortraitMapper.xml
new file mode 100644
index 0000000..42056a4
--- /dev/null
+++ b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsPortraitMapper.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsRankMapper.xml b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsRankMapper.xml
new file mode 100644
index 0000000..abd63f2
--- /dev/null
+++ b/yudao-module-crm/src/main/resources/mapper/statistics/CrmStatisticsRankMapper.xml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yudao-module-crm/src/test/resources/application-unit-test.yaml b/yudao-module-crm/src/test/resources/application-unit-test.yaml
new file mode 100644
index 0000000..a55b301
--- /dev/null
+++ b/yudao-module-crm/src/test/resources/application-unit-test.yaml
@@ -0,0 +1,49 @@
+spring:
+ main:
+ lazy-initialization: true # 开启懒加载,加快速度
+ banner-mode: off # 单元测试,禁用 Banner
+
+--- #################### 数据库相关配置 ####################
+
+spring:
+ # 数据源配置项
+ datasource:
+ name: ruoyi-vue-pro
+ url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
+ driver-class-name: org.h2.Driver
+ username: sa
+ password:
+ druid:
+ async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
+ initial-size: 1 # 单元测试,配置为 1,提升启动速度
+ sql:
+ init:
+ schema-locations: classpath:/sql/create_tables.sql
+
+ # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
+ data:
+ redis:
+ host: 127.0.0.1 # 地址
+ port: 16379 # 端口(单元测试,使用 16379 端口)
+ database: 0 # 数据库索引
+
+mybatis-plus:
+ lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
+ type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
+
+--- #################### 定时任务相关配置 ####################
+
+--- #################### 配置中心相关配置 ####################
+
+--- #################### 服务保障相关配置 ####################
+
+# Lock4j 配置项(单元测试,禁用 Lock4j)
+
+--- #################### 监控相关配置 ####################
+
+--- #################### 芋道相关配置 ####################
+
+# 芋道配置项,设置当前项目所有自定义的配置
+yudao:
+ info:
+ base-package: cn.iocoder.yudao
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml b/yudao-module-crm/src/test/resources/logback.xml
index 1d071e4..1d071e4 100644
--- a/yudao-module-crm/yudao-module-crm-biz/src/test/resources/logback.xml
+++ b/yudao-module-crm/src/test/resources/logback.xml
diff --git a/yudao-module-crm/yudao-module-crm-api/pom.xml b/yudao-module-crm/yudao-module-crm-api/pom.xml
deleted file mode 100644
index 94e1296..0000000
--- a/yudao-module-crm/yudao-module-crm-api/pom.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
- cn.iocoder.boot
- yudao-module-crm
- ${revision}
-
- 4.0.0
- yudao-module-crm-api
- jar
-
- ${project.artifactId}
-
- crm 模块 API,暴露给其它模块调用
-
-
-
-
- cn.iocoder.boot
- yudao-common
-
-
-
-
- org.springframework.boot
- spring-boot-starter-validation
- true
-
-
-
-
diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml
deleted file mode 100644
index 679ec1e..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/pom.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-
-
-
- cn.iocoder.boot
- yudao-module-crm
- ${revision}
-
- 4.0.0
- yudao-module-crm-biz
-
- ${project.artifactId}
-
- crm 包下,客户关系管理(Customer Relationship Management)。
- 例如说:客户、联系人、商机、合同、回款等等
-
-
-
-
- cn.iocoder.boot
- yudao-module-system-api
- ${revision}
-
-
- cn.iocoder.boot
- yudao-module-infra-api
- ${revision}
-
-
- cn.iocoder.boot
- yudao-module-crm-api
- ${revision}
-
-
- cn.iocoder.boot
- yudao-module-bpm-api
- ${revision}
-
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-biz-ip
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-biz-tenant
-
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-web
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-security
-
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-mybatis
-
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-excel
-
-
-
-
- cn.iocoder.boot
- yudao-spring-boot-starter-test
-
-
-
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java
deleted file mode 100644
index 09de726..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/web/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * crm 模块的 web 拓展封装
- */
-package cn.iocoder.yudao.module.crm.framework.web;
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
deleted file mode 100644
index 2214e6b..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * 定时任务
- */
-package cn.iocoder.yudao.module.crm.job;
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
deleted file mode 100644
index bd9c164..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.business;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * 商机状态 Service 接口
- *
- * @author ljlleo
- */
-public interface CrmBusinessStatusService {
-
- /**
- * 创建商机状态
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createBusinessStatus(@Valid CrmBusinessStatusSaveReqVO createReqVO);
-
- /**
- * 更新商机状态
- *
- * @param updateReqVO 更新信息
- */
- void updateBusinessStatus(@Valid CrmBusinessStatusSaveReqVO updateReqVO);
-
- /**
- * 删除商机状态
- *
- * @param id 编号
- */
- void deleteBusinessStatusType(Long id);
-
- /**
- * 获得商机状态组
- *
- * @param id 编号
- * @return 商机状态组
- */
- CrmBusinessStatusTypeDO getBusinessStatusType(Long id);
-
- /**
- * 校验商机状态组
- *
- * @param id 编号
- */
- void validateBusinessStatusType(Long id);
-
- /**
- * 获得商机状态组列表
- *
- * @return 商机状态组列表
- */
- List getBusinessStatusTypeList();
-
- /**
- * 获得商机状态组分页
- *
- * @param pageReqVO 分页查询
- * @return 商机状态组分页
- */
- PageResult getBusinessStatusTypePage(PageParam pageReqVO);
-
- /**
- * 获得商机状态组列表
- *
- * @param ids 编号数组
- * @return 商机状态组列表
- */
- List getBusinessStatusTypeList(Collection ids);
-
- /**
- * 获得商机状态组 Map
- *
- * @param ids 编号数组
- * @return 商机状态组 Map
- */
- default Map getBusinessStatusTypeMap(Collection ids) {
- return convertMap(getBusinessStatusTypeList(ids), CrmBusinessStatusTypeDO::getId);
- }
-
- /**
- * 获得指定类型的商机状态列表
- *
- * @param typeId 商机状态组编号
- * @return 商机状态列表
- */
- List getBusinessStatusListByTypeId(Long typeId);
-
- /**
- * 获得商机状态列表
- *
- * @param ids 编号数组
- * @return 商机状态列表
- */
- List getBusinessStatusList(Collection ids);
-
- /**
- * 获得商机状态 Map
- *
- * @param ids 编号数组
- * @return 商机状态 Map
- */
- default Map getBusinessStatusMap(Collection ids) {
- return convertMap(getBusinessStatusList(ids), CrmBusinessStatusDO::getId);
- }
-
- /**
- * 获得商机状态
- *
- * @param id 编号
- * @return 商机状态
- */
- CrmBusinessStatusDO getBusinessStatus(Long id);
-
- /**
- * 校验商机状态
- *
- * @param statusTypeId 商机状态组编号
- * @param statusId 商机状态编号
- */
- CrmBusinessStatusDO validateBusinessStatus(Long statusTypeId, Long statusId);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
deleted file mode 100644
index 26d0836..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.clue;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
-import jakarta.validation.Valid;
-
-import java.time.LocalDateTime;
-
-/**
- * 线索 Service 接口
- *
- * @author Wanwan
- */
-public interface CrmClueService {
-
- /**
- * 创建线索
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createClue(@Valid CrmClueSaveReqVO createReqVO);
-
- /**
- * 更新线索
- *
- * @param updateReqVO 更新信息
- */
- void updateClue(@Valid CrmClueSaveReqVO updateReqVO);
-
- /**
- * 更新线索相关的跟进信息
- *
- * @param id 编号
- * @param contactNextTime 下次联系时间
- * @param contactLastContent 最后联系内容
- */
- void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
-
- /**
- * 删除线索
- *
- * @param id 编号
- */
- void deleteClue(Long id);
-
- /**
- * 获得线索
- *
- * @param id 编号
- * @return 线索
- */
- CrmClueDO getClue(Long id);
-
- /**
- * 获得线索分页
- *
- * @param pageReqVO 分页查询
- * @param userId 用户编号
- * @return 线索分页
- */
- PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId);
-
- /**
- * 线索转移
- *
- * @param reqVO 请求
- * @param userId 用户编号
- */
- void transferClue(CrmClueTransferReqVO reqVO, Long userId);
-
- /**
- * 线索转化为客户
- *
- * @param id 线索编号
- * @param userId 用户编号
- */
- void transformClue(Long id, Long userId);
-
- /**
- * 获得分配给我的、待跟进的线索数量
- *
- * @param userId 用户编号
- * @return 数量
- */
- Long getFollowClueCount(Long userId);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
deleted file mode 100644
index 2deaf00..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.contact;
-
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusiness2ReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
-import jakarta.validation.Valid;
-
-import java.util.List;
-
-/**
- * CRM 联系人与商机的关联 Service 接口
- *
- * @author 芋道源码
- */
-public interface CrmContactBusinessService {
-
- /**
- * 创建联系人与商机的关联【通过联系人,关联商机】
- *
- * @param createReqVO 创建信息
- */
- void createContactBusinessList(@Valid CrmContactBusinessReqVO createReqVO);
-
- /**
- * 创建联系人与商机的关联【通过商机,关联联系人】
- *
- * @param createReqVO 创建信息
- */
- void createContactBusinessList2(@Valid CrmContactBusiness2ReqVO createReqVO);
-
- /**
- * 删除联系人与商机的关联【通过联系人,取关商机】
- *
- * @param deleteReqVO 删除信息
- */
- void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
-
- /**
- * 删除联系人与商机的关联【通过商机,取关联系人】
- *
- * @param deleteReqVO 删除信息
- */
- void deleteContactBusinessList2(@Valid CrmContactBusiness2ReqVO deleteReqVO);
-
- /**
- * 删除联系人与商机的关联,基于联系人编号
- *
- * @param contactId 联系人编号
- */
- void deleteContactBusinessByContactId(Long contactId);
-
- /**
- * 获得联系人与商机的关联列表,基于联系人编号
- *
- * @param contactId 联系人编号
- * @return 联系人商机关联
- */
- List getContactBusinessListByContactId(Long contactId);
-
- /**
- * 获得联系人与商机的关联列表,基于商机编号
- *
- * @param businessId 商机编号
- * @return 联系人商机关联
- */
- List getContactBusinessListByBusinessId(Long businessId);
-
-}
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java
deleted file mode 100644
index c9379dc..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractConfigServiceImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.contract;
-
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.config.CrmContractConfigSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractConfigDO;
-import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractConfigMapper;
-import com.mzt.logapi.context.LogRecordContext;
-import com.mzt.logapi.starter.annotation.LogRecord;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Objects;
-
-import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
-
-/**
- * 合同配置 Service 实现类
- *
- * @author 芋道源码
- */
-@Service
-@Validated
-public class CrmContractConfigServiceImpl implements CrmContractConfigService {
-
- @Resource
- private CrmContractConfigMapper contractConfigMapper;
-
- @Override
- public CrmContractConfigDO getContractConfig() {
- return contractConfigMapper.selectOne();
- }
-
- @Override
- @LogRecord(type = CRM_CONTRACT_CONFIG_TYPE, subType = CRM_CONTRACT_CONFIG_SUB_TYPE, bizNo = "{{#configId}}",
- success = CRM_CONTRACT_CONFIG_SUCCESS)
- public void saveContractConfig(CrmContractConfigSaveReqVO saveReqVO) {
- // 1. 存在,则进行更新
- CrmContractConfigDO dbConfig = getContractConfig();
- CrmContractConfigDO config = BeanUtils.toBean(saveReqVO, CrmContractConfigDO.class);
- if (Objects.nonNull(dbConfig)) {
- contractConfigMapper.updateById(config.setId(dbConfig.getId()));
- // 记录操作日志上下文
- LogRecordContext.putVariable("isConfigUpdate", Boolean.TRUE);
- LogRecordContext.putVariable("configId", config.getId());
- return;
- }
-
- // 2. 不存在,则进行插入
- contractConfigMapper.insert(config);
- // 记录操作日志上下文
- LogRecordContext.putVariable("isConfigUpdate", Boolean.FALSE);
- LogRecordContext.putVariable("configId", config.getId());
- }
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java
deleted file mode 100644
index 14d3c66..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractStatusListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.contract.listener;
-
-import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
-import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEventListener;
-import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
-import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-/**
- * 合同审批的结果的监听器实现类
- *
- * @author HUIHUI
- */
-@Component
-public class CrmContractStatusListener extends BpmProcessInstanceStatusEventListener {
-
- @Resource
- private CrmContractService contractService;
-
- @Override
- public String getProcessDefinitionKey() {
- return CrmContractServiceImpl.BPM_PROCESS_DEFINITION_KEY;
- }
-
- @Override
- protected void onEvent(BpmProcessInstanceStatusEvent event) {
- contractService.updateContractAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
- }
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
deleted file mode 100644
index f67f377..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.customer;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
-import jakarta.validation.Valid;
-
-import java.util.List;
-
-/**
- * 客户限制配置 Service 接口
- *
- * @author Wanwan
- */
-public interface CrmCustomerLimitConfigService {
-
- /**
- * 创建客户限制配置
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO createReqVO);
-
- /**
- * 更新客户限制配置
- *
- * @param updateReqVO 更新信息
- */
- void updateCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO updateReqVO);
-
- /**
- * 删除客户限制配置
- *
- * @param id 编号
- */
- void deleteCustomerLimitConfig(Long id);
-
- /**
- * 获得客户限制配置
- *
- * @param id 编号
- * @return 客户限制配置
- */
- CrmCustomerLimitConfigDO getCustomerLimitConfig(Long id);
-
- /**
- * 获得客户限制配置分页
- *
- * @param pageReqVO 分页查询
- * @return 客户限制配置分页
- */
- PageResult getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO);
-
- /**
- * 查询用户对应的配置列表
- *
- * @param type 类型
- * @param userId 用户类型
- */
- List getCustomerLimitConfigListByUserId(Integer type, Long userId);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java
deleted file mode 100644
index 9099b19..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.customer;
-
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
-import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerPoolConfigMapper;
-import com.mzt.logapi.context.LogRecordContext;
-import com.mzt.logapi.starter.annotation.LogRecord;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Objects;
-
-import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
-
-/**
- * 客户公海配置 Service 实现类
- *
- * @author Wanwan
- */
-@Service
-@Validated
-public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigService {
-
- @Resource
- private CrmCustomerPoolConfigMapper customerPoolConfigMapper;
-
- @Override
- public CrmCustomerPoolConfigDO getCustomerPoolConfig() {
- return customerPoolConfigMapper.selectOne();
- }
-
- @Override
- @LogRecord(type = CRM_CUSTOMER_POOL_CONFIG_TYPE, subType = CRM_CUSTOMER_POOL_CONFIG_SUB_TYPE, bizNo = "{{#poolConfigId}}",
- success = CRM_CUSTOMER_POOL_CONFIG_SUCCESS)
- public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) {
- // 1. 存在,则进行更新
- CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig();
- CrmCustomerPoolConfigDO poolConfig = BeanUtils.toBean(saveReqVO, CrmCustomerPoolConfigDO.class);
- if (Objects.nonNull(dbConfig)) {
- customerPoolConfigMapper.updateById(poolConfig.setId(dbConfig.getId()));
- // 记录操作日志上下文
- LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.TRUE);
- LogRecordContext.putVariable("poolConfigId", poolConfig.getId());
- return;
- }
-
- // 2. 不存在,则进行插入
- customerPoolConfigMapper.insert(poolConfig);
- // 记录操作日志上下文
- LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.FALSE);
- LogRecordContext.putVariable("poolConfigId", poolConfig.getId());
- }
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
deleted file mode 100644
index 70b4f9f..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.customer;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO;
-import jakarta.validation.Valid;
-
-import java.time.LocalDateTime;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * 客户 Service 接口
- *
- * @author Wanwan
- */
-public interface CrmCustomerService {
-
- /**
- * 创建客户
- *
- * @param createReqVO 创建信息
- * @param userId 用户编号
- * @return 编号
- */
- Long createCustomer(@Valid CrmCustomerSaveReqVO createReqVO, Long userId);
-
- /**
- * 更新客户
- *
- * @param updateReqVO 更新信息
- */
- void updateCustomer(@Valid CrmCustomerSaveReqVO updateReqVO);
-
- /**
- * 更新客户的跟进状态
- *
- * @param id 编号
- * @param dealStatus 跟进状态
- */
- void updateCustomerDealStatus(Long id, Boolean dealStatus);
-
- /**
- * 更新客户相关的跟进信息
- *
- * @param id 编号
- * @param contactNextTime 下次联系时间
- * @param contactLastContent 最后联系内容
- */
- void updateCustomerFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
-
- /**
- * 删除客户
- *
- * @param id 编号
- */
- void deleteCustomer(Long id);
-
- /**
- * 获得客户
- *
- * @param id 编号
- * @return 客户
- */
- CrmCustomerDO getCustomer(Long id);
-
- /**
- * 获得客户列表
- *
- * @param ids 客户编号数组
- * @return 客户列表
- * @author ljlleo
- */
- List getCustomerList(Collection ids);
-
- /**
- * 获得客户 Map
- *
- * @param ids 客户编号数组
- * @return 客户 Map
- */
- default Map getCustomerMap(Collection ids) {
- return convertMap(getCustomerList(ids), CrmCustomerDO::getId);
- }
-
- /**
- * 获得客户分页
- *
- * @param pageReqVO 分页查询
- * @param userId 用户编号
- * @return 客户分页
- */
- PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId);
-
- /**
- * 获得放入公海提醒的客户分页
- *
- * @param pageVO 分页查询
- * @param userId 用户编号
- * @return 客户分页
- */
- PageResult getPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, Long userId);
-
- /**
- * 获得待进入公海的客户数量
- *
- * @param userId 用户编号
- * @return 提醒数量
- */
- Long getPutPoolRemindCustomerCount(Long userId);
-
- /**
- * 获得今日需联系客户数量
- *
- * @param userId 用户编号
- * @return 提醒数量
- */
- Long getTodayContactCustomerCount(Long userId);
-
- /**
- * 获得分配给我的客户数量
- *
- * @param userId 用户编号
- * @return 提醒数量
- */
- Long getFollowCustomerCount(Long userId);
-
- /**
- * 校验客户是否存在
- *
- * @param id 编号
- */
- void validateCustomer(Long id);
-
- /**
- * 客户转移
- *
- * @param reqVO 请求
- * @param userId 用户编号
- */
- void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId);
-
- /**
- * 锁定/解锁客户
- *
- * @param lockReqVO 更新信息
- * @param userId 用户编号
- */
- void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId);
-
- /**
- * 创建客户
- *
- * @param customerCreateReq 请求信息
- * @param userId 用户编号
- * @return 客户列表
- */
- Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId);
-
- /**
- * 批量导入客户
- *
- * @param importCustomers 导入客户列表
- * @param importReqVO 请求
- * @return 导入结果
- */
- CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO);
-
- // ==================== 公海相关操作 ====================
-
- /**
- * 客户放入公海
- *
- * @param id 客户编号
- */
- void putCustomerPool(Long id);
-
- /**
- * 领取公海客户
- *
- * @param ids 要领取的客户编号数组
- * @param ownerUserId 负责人
- * @param isReceive 是/否领取;true - 领取;false - 分配
- */
- void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive);
-
- /**
- * 【系统】客户自动掉入公海
- *
- * @return 掉入公海数量
- */
- int autoPutCustomerPool();
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java
deleted file mode 100644
index 58d1476..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.customer.bo;
-
-import cn.iocoder.yudao.framework.common.validation.Mobile;
-import cn.iocoder.yudao.framework.common.validation.Telephone;
-import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.Size;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-
-/**
- * 客户创建 Create Req BO
- *
- * @author HUIHUI
- */
-@Data
-public class CrmCustomerCreateReqBO {
-
- /**
- * 客户名称
- */
- @NotEmpty(message = "客户名称不能为空")
- private String name;
- /**
- * 跟进状态
- */
- private Boolean followUpStatus;
- /**
- * 锁定状态
- */
- private Boolean lockStatus;
- /**
- * 成交状态
- */
- private Boolean dealStatus;
- /**
- * 所属行业
- *
- * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
- */
- private Integer industryId;
- /**
- * 客户等级
- *
- * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL}
- */
- private Integer level;
- /**
- * 客户来源
- *
- * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE}
- */
- private Integer source;
-
- /**
- * 手机
- */
- @Mobile
- private String mobile;
- /**
- * 电话
- */
- @Telephone
- private String telephone;
- /**
- * QQ
- */
- private String qq;
- /**
- * wechat
- */
- private String wechat;
-
- /**
- * 邮箱
- */
- @Email(message = "邮箱格式不正确")
- private String email;
-
- /**
- * 客户描述
- */
- @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符")
- private String description;
- /**
- * 备注
- */
- private String remark;
- /**
- * 负责人的用户编号
- *
- * 关联 AdminUserDO 的 id 字段
- */
- private Long ownerUserId;
- /**
- * 所在地
- *
- * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
- */
- private Integer areaId;
- /**
- * 详细地址
- */
- private String detailAddress;
-
- /**
- * 最后跟进时间
- */
- private LocalDateTime contactLastTime;
- /**
- * 最后跟进内容
- */
- private String contactLastContent;
- /**
- * 下次联系时间
- */
- private LocalDateTime contactNextTime;
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java
deleted file mode 100644
index d2a7cb8..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.followup;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO;
-import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 跟进记录 Service 接口
- *
- * @author 芋道源码
- */
-public interface CrmFollowUpRecordService {
-
- /**
- * 创建跟进记录 (数据权限基于 bizType、 bizId)
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createFollowUpRecord(@Valid CrmFollowUpRecordSaveReqVO createReqVO);
-
- /**
- * 创建更进
- *
- * @param list 请求
- */
- void createFollowUpRecordBatch(List list);
-
- /**
- * 删除跟进记录 (数据权限基于 bizType、 bizId)
- *
- * @param id 编号
- * @param userId 用户编号
- */
- void deleteFollowUpRecord(Long id, Long userId);
-
- /**
- * 删除跟进
- *
- * @param bizType 模块类型
- * @param bizId 模块数据编号
- */
- void deleteFollowUpRecordByBiz(Integer bizType, Long bizId);
-
- /**
- * 获得跟进记录
- *
- * @param id 编号
- * @return 跟进记录
- */
- CrmFollowUpRecordDO getFollowUpRecord(Long id);
-
- /**
- * 获得跟进记录分页 (数据权限基于 bizType、 bizId)
- *
- * @param pageReqVO 分页查询
- * @return 跟进记录分页
- */
- PageResult getFollowUpRecordPage(CrmFollowUpRecordPageReqVO pageReqVO);
-
- /**
- * 获取跟进记录
- *
- * @param bizType 模块类型
- * @param bizIds 模块数据编号
- * @return 跟进列表
- */
- List getFollowUpRecordByBiz(Integer bizType, Collection bizIds);
-
-}
\ No newline at end of file
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java
deleted file mode 100644
index dec219e..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.followup.bo;
-
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
-import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
-import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * 跟进信息 Create Req BO
- *
- * @author HUIHUI
- */
-@Data
-public class CrmFollowUpCreateReqBO {
-
- /**
- * 数据类型
- *
- * 枚举 {@link CrmBizTypeEnum}
- */
- @NotNull(message = "数据类型不能为空")
- private Integer bizType;
- /**
- * 数据编号
- *
- * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段
- */
- @NotNull(message = "数据编号不能为空")
- private Long bizId;
-
- /**
- * 跟进类型
- *
- * 关联 {@link DictTypeConstants#CRM_FOLLOW_UP_TYPE} 字典
- */
- @NotNull(message = "跟进类型不能为空")
- private Integer type;
- /**
- * 跟进内容
- */
- @NotEmpty(message = "跟进内容不能为空")
- private String content;
- /**
- * 下次联系时间
- */
- @NotNull(message = "下次联系时间不能为空")
- private LocalDateTime nextTime;
-
- /**
- * 图片
- */
- private List picUrls;
- /**
- * 附件
- */
- private List fileUrls;
-
- /**
- * 关联的商机编号数组
- *
- * 关联 {@link CrmBusinessDO#getId()}
- */
- private List businessIds;
-
- /**
- * 关联的联系人编号数组
- *
- * 关联 {@link CrmContactDO#getId()}
- */
- private List contactIds;
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
deleted file mode 100644
index 2ff8113..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.permission;
-
-
-import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionSaveReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO;
-import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
-import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * crm 数据权限 Service 接口
- *
- * @author HUIHUI
- */
-public interface CrmPermissionService {
-
- /**
- * 创建数据权限
- *
- * @param reqVO 创建信息
- * @param userId 用户编号
- */
- void createPermission(CrmPermissionSaveReqVO reqVO, Long userId);
-
- /**
- * 创建数据权限
- *
- * @param createReqBO 创建信息
- * @return 编号
- */
- Long createPermission(@Valid CrmPermissionCreateReqBO createReqBO);
-
- /**
- * 创建数据权限
- *
- * @param createReqBOs 创建信息
- */
- void createPermissionBatch(@Valid List createReqBOs);
-
- /**
- * 更新数据权限
- *
- * @param updateReqVO 更新信息
- */
- void updatePermission(CrmPermissionUpdateReqVO updateReqVO);
-
- /**
- * 数据权限转移
- *
- * @param crmPermissionTransferReqBO 数据权限转移请求
- */
- void transferPermission(@Valid CrmPermissionTransferReqBO crmPermissionTransferReqBO);
-
- /**
- * 删除数据权限
- *
- * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
- * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
- * @param level 数据权限级别,关联 {@link CrmPermissionLevelEnum}
- */
- void deletePermission(Integer bizType, Long bizId, Integer level);
-
- /**
- * 删除数据权限
- *
- * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
- * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
- */
- void deletePermission(Integer bizType, Long bizId);
-
- /**
- * 批量删除数据权限
- *
- * @param ids 权限编号
- * @param userId 用户编号
- */
- void deletePermissionBatch(Collection ids, Long userId);
-
- /**
- * 删除指定用户数据权限
- *
- * @param id 权限编号
- * @param userId 用户编号
- */
- void deleteSelfPermission(Long id, Long userId);
-
- /**
- * 获取数据权限列表,通过 数据类型 x 某个数据
- *
- * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
- * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
- * @return Crm 数据权限列表
- */
- List getPermissionListByBiz(Integer bizType, Long bizId);
-
- /**
- * 获取数据权限列表,通过 数据类型 x 某个数据
- *
- * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
- * @param bizIds 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
- * @return Crm 数据权限列表
- */
- List getPermissionListByBiz(Integer bizType, Collection bizIds);
-
- /**
- * 获取用户参与的模块数据列表
- *
- * @param bizType 模块类型
- * @param userId 用户编号
- * @return 模块数据列表
- */
- List getPermissionListByBizTypeAndUserId(Integer bizType, Long userId);
-
- /**
- * 校验是否有指定数据的操作权限
- *
- * @param bizType 数据类型,关联 {@link CrmBizTypeEnum}
- * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId()
- * @param userId 用户编号
- * @param level 权限级别
- * @return 是否有权限
- */
- boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java
deleted file mode 100644
index f4b4bb3..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionCreateReqBO.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.permission.bo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
-import lombok.Data;
-
-import jakarta.validation.constraints.NotNull;
-
-/**
- * crm 数据权限 Create Req BO
- *
- * @author HUIHUI
- */
-@Data
-public class CrmPermissionCreateReqBO {
-
- /**
- * 当前登录用户编号
- */
- @NotNull(message = "用户编号不能为空")
- private Long userId;
-
- /**
- * Crm 类型
- */
- @NotNull(message = "Crm 类型不能为空")
- @InEnum(CrmBizTypeEnum.class)
- private Integer bizType;
- /**
- * 数据编号
- */
- @NotNull(message = "Crm 数据编号不能为空")
- private Long bizId;
-
- /**
- * 权限级别
- */
- @NotNull(message = "权限级别不能为空")
- @InEnum(CrmPermissionLevelEnum.class)
- private Integer level;
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java
deleted file mode 100644
index 52f8a97..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.permission.bo;
-
-import cn.iocoder.yudao.framework.common.validation.InEnum;
-import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
-import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.NoArgsConstructor;
-
-/**
- * 数据权限转移 Request BO
- *
- * @author HUIHUI
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class CrmPermissionTransferReqBO {
-
- /**
- * 当前登录用户编号
- */
- @NotNull(message = "用户编号不能为空")
- private Long userId;
-
- /**
- * CRM 类型
- */
- @NotNull(message = "Crm 类型不能为空")
- @InEnum(CrmBizTypeEnum.class)
- private Integer bizType;
- /**
- * 数据编号
- */
- @NotNull(message = "CRM 数据编号不能为空")
- private Long bizId;
-
- /**
- * 新负责人的用户编号
- */
- @NotNull(message = "新负责人的用户编号不能为空")
- private Long newOwnerUserId;
-
- /**
- * 老负责人加入团队后的权限级别。如果 null 说明移除
- *
- * 关联 {@link CrmPermissionLevelEnum}
- */
- private Integer oldOwnerPermissionLevel;
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java
deleted file mode 100644
index c68c0cf..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryService.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.product;
-
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * CRM 产品分类 Service 接口
- *
- * @author ZanGe丶
- */
-public interface CrmProductCategoryService {
-
- /**
- * 创建产品分类
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createProductCategory(@Valid CrmProductCategoryCreateReqVO createReqVO);
-
- /**
- * 更新产品分类
- *
- * @param updateReqVO 更新信息
- */
- void updateProductCategory(@Valid CrmProductCategoryCreateReqVO updateReqVO);
-
- /**
- * 删除产品分类
- *
- * @param id 编号
- */
- void deleteProductCategory(Long id);
-
- /**
- * 获得产品分类
- *
- * @param id 编号
- * @return 产品分类
- */
- CrmProductCategoryDO getProductCategory(Long id);
-
- /**
- * 获得产品分类列表
- *
- * @param listReqVO 列表请求
- * @return 产品分类列表
- */
- List getProductCategoryList(CrmProductCategoryListReqVO listReqVO);
-
- /**
- * 获得产品分类列表
- *
- * @param ids 编号数组
- * @return 产品分类列表
- */
- List getProductCategoryList(Collection ids);
-
- /**
- * 获得产品分类 Map
- *
- * @param ids 编号数组
- * @return 产品分类 Map
- */
- default Map getProductCategoryMap(Collection ids) {
- return convertMap(getProductCategoryList(ids), CrmProductCategoryDO::getId);
- }
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
deleted file mode 100644
index ce16888..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.product;
-
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryCreateReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
-import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductCategoryMapper;
-import com.mzt.logapi.context.LogRecordContext;
-import com.mzt.logapi.starter.annotation.LogRecord;
-import jakarta.annotation.Resource;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO.PARENT_ID_NULL;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
-
-/**
- * CRM 产品分类 Service 实现类
- *
- * @author ZanGe丶
- */
-@Service
-@Validated
-public class CrmProductCategoryServiceImpl implements CrmProductCategoryService {
-
- @Resource(name = "crmProductCategoryMapper")
- private CrmProductCategoryMapper productCategoryMapper;
-
- @Resource
- @Lazy // 延迟加载,解决循环依赖问题
- private CrmProductService crmProductService;
-
- @Override
- @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_CREATE_SUB_TYPE, bizNo = "{{#productCategoryId}}",
- success = CRM_PRODUCT_CATEGORY_CREATE_SUCCESS)
- public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) {
- // 1.1 校验父分类存在
- validateParentProductCategory(createReqVO.getParentId());
- // 1.2 分类名称是否存在
- validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName());
-
- // 2. 插入分类
- CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class);
- productCategoryMapper.insert(category);
-
- // 3. 记录操作日志上下文
- LogRecordContext.putVariable("productCategoryId", category.getId());
- return category.getId();
- }
-
- @Override
- @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
- success = CRM_PRODUCT_CATEGORY_UPDATE_SUCCESS)
- public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) {
- // 1.1 校验存在
- validateProductCategoryExists(updateReqVO.getId());
- // 1.2 校验父分类存在
- validateParentProductCategory(updateReqVO.getParentId());
- // 1.3 分类名称是否存在
- validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
-
- // 2. 更新分类
- CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class);
- productCategoryMapper.updateById(updateObj);
- }
-
- private void validateProductCategoryExists(Long id) {
- if (productCategoryMapper.selectById(id) == null) {
- throw exception(PRODUCT_CATEGORY_NOT_EXISTS);
- }
- }
-
- private void validateParentProductCategory(Long id) {
- // 如果是根分类,无需验证
- if (Objects.equals(id, PARENT_ID_NULL)) {
- return;
- }
- // 父分类不存在
- CrmProductCategoryDO category = productCategoryMapper.selectById(id);
- if (category == null) {
- throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS);
- }
- // 父分类不能是二级分类
- if (!Objects.equals(category.getParentId(), PARENT_ID_NULL)) {
- throw exception(PRODUCT_CATEGORY_PARENT_NOT_FIRST_LEVEL);
- }
- }
-
- private void validateProductNameExists(Long id, Long parentId, String name) {
- CrmProductCategoryDO category = productCategoryMapper.selectByParentIdAndName(parentId, name);
- if (category == null
- || category.getId().equals(id)) {
- return;
- }
- throw exception(PRODUCT_CATEGORY_EXISTS);
- }
-
- @Override
- @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_DELETE_SUB_TYPE, bizNo = "{{#id}}",
- success = CRM_PRODUCT_CATEGORY_DELETE_SUCCESS)
- public void deleteProductCategory(Long id) {
- // 1.1 校验存在
- validateProductCategoryExists(id);
- // 1.2 校验是否还有子分类
- if (productCategoryMapper.selectCountByParentId(id) > 0) {
- throw exception(PRODUCT_CATEGORY_EXISTS_CHILDREN);
- }
- // 1.3 校验是否被产品使用
- if (crmProductService.getProductByCategoryId(id) > 0) {
- throw exception(PRODUCT_CATEGORY_USED);
- }
- // 2. 删除
- productCategoryMapper.deleteById(id);
- }
-
- @Override
- public CrmProductCategoryDO getProductCategory(Long id) {
- return productCategoryMapper.selectById(id);
- }
-
- @Override
- public List getProductCategoryList(CrmProductCategoryListReqVO listReqVO) {
- return productCategoryMapper.selectList(listReqVO);
- }
-
- @Override
- public List getProductCategoryList(Collection ids) {
- return productCategoryMapper.selectBatchIds(ids);
- }
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java
deleted file mode 100644
index 9379734..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.product;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * CRM 产品 Service 接口
- *
- * @author ZanGe丶
- */
-public interface CrmProductService {
-
- /**
- * 创建产品
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createProduct(@Valid CrmProductSaveReqVO createReqVO);
-
- /**
- * 更新产品
- *
- * @param updateReqVO 更新信息
- */
- void updateProduct(@Valid CrmProductSaveReqVO updateReqVO);
-
- /**
- * 删除产品
- *
- * @param id 编号
- */
- void deleteProduct(Long id);
-
- /**
- * 获得产品
- *
- * @param id 编号
- * @return 产品
- */
- CrmProductDO getProduct(Long id);
-
- /**
- * 获得产品列表
- *
- * @param ids 编号
- * @return 产品列表
- */
- List getProductList(Collection ids);
-
- /**
- * 获得产品 Map
- *
- * @param ids 编号
- * @return 产品 Map
- */
- default Map getProductMap(Collection ids) {
- return convertMap(getProductList(ids), CrmProductDO::getId);
- }
-
- /**
- * 获得产品分页
- *
- * @param pageReqVO 分页查询
- * @return 产品分页
- */
- PageResult getProductPage(CrmProductPageReqVO pageReqVO);
-
- /**
- * 获得产品数量
- *
- * @param categoryId 分类编号
- * @return 产品
- */
- Long getProductByCategoryId(Long categoryId);
-
- /**
- * 获得指定状态的产品列表
- *
- * @param status 状态
- * @return 产品列表
- */
- List getProductListByStatus(Integer status);
-
- /**
- * 校验产品们的有效性
- *
- * @param ids 编号数组
- * @return 产品列表
- */
- List validProductList(Collection ids);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
deleted file mode 100644
index b5d3cc2..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.receivable;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO;
-import jakarta.validation.Valid;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * CRM 回款计划 Service 接口
- *
- * @author 芋道源码
- */
-public interface CrmReceivablePlanService {
-
- /**
- * 创建回款计划
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createReceivablePlan(@Valid CrmReceivablePlanSaveReqVO createReqVO);
-
- /**
- * 更新回款计划
- *
- * @param updateReqVO 更新信息
- */
- void updateReceivablePlan(@Valid CrmReceivablePlanSaveReqVO updateReqVO);
-
- /**
- * 更新回款计划关联的回款编号
- *
- * @param id 编号
- * @param receivableId 回款编号
- */
- void updateReceivablePlanReceivableId(Long id, Long receivableId);
-
- /**
- * 删除回款计划
- *
- * @param id 编号
- */
- void deleteReceivablePlan(Long id);
-
- /**
- * 获得回款计划
- *
- * @param id 编号
- * @return 回款计划
- */
- CrmReceivablePlanDO getReceivablePlan(Long id);
-
- /**
- * 获得回款计划列表
- *
- * @param ids 编号
- * @return 回款计划列表
- */
- List getReceivablePlanList(Collection ids);
-
- /**
- * 获得回款计划分页
- *
- * 数据权限:基于 {@link CrmReceivablePlanDO} 读取
- *
- * @param pageReqVO 分页查询
- * @param userId 用户编号
- * @return 回款计划分页
- */
- PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId);
-
- /**
- * 获得回款计划分页,基于指定客户
- *
- * 数据权限:基于 {@link CrmCustomerDO} 读取
- *
- * @param pageReqVO 分页查询
- * @return 回款计划分页
- */
- PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO);
-
- /**
- * 获得待回款提醒数量
- *
- * @param userId 用户编号
- * @return 提醒数量
- */
- Long getReceivablePlanRemindCount(Long userId);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
deleted file mode 100644
index f6ac8c3..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.receivable;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO;
-import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO;
-import jakarta.validation.Valid;
-
-import java.math.BigDecimal;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
-
-/**
- * CRM 回款 Service 接口
- *
- * @author 赤焰
- */
-public interface CrmReceivableService {
-
- /**
- * 创建回款
- *
- * @param createReqVO 创建信息
- * @return 编号
- */
- Long createReceivable(@Valid CrmReceivableSaveReqVO createReqVO);
-
- /**
- * 更新回款
- *
- * @param updateReqVO 更新信息
- */
- void updateReceivable(@Valid CrmReceivableSaveReqVO updateReqVO);
-
- /**
- * 更新回款流程审批结果
- *
- * @param id 回款编号
- * @param bpmResult BPM 审批结果
- */
- void updateReceivableAuditStatus(Long id, Integer bpmResult);
-
- /**
- * 删除回款
- *
- * @param id 编号
- */
- void deleteReceivable(Long id);
-
- /**
- * 发起回款审批流程
- *
- * @param id 回款编号
- * @param userId 用户编号
- */
- void submitReceivable(Long id, Long userId);
-
- /**
- * 获得回款
- *
- * @param id 编号
- * @return 回款
- */
- CrmReceivableDO getReceivable(Long id);
-
- /**
- * 获得回款列表
- *
- * @param ids 编号
- * @return 回款列表
- */
- List getReceivableList(Collection ids);
-
- /**
- * 获得回款 Map
- *
- * @param ids 编号
- * @return 回款 Map
- */
- default Map getReceivableMap(Collection ids) {
- return convertMap(getReceivableList(ids), CrmReceivableDO::getId);
- }
-
- /**
- * 获得回款分页
- *
- * 数据权限:基于 {@link CrmReceivableDO} 读取
- *
- * @param pageReqVO 分页查询
- * @param userId 用户编号
- * @return 回款分页
- */
- PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId);
-
- /**
- * 获得回款分页,基于指定客户
- *
- * 数据权限:基于 {@link CrmCustomerDO} 读取
- *
- * @param pageReqVO 分页查询
- * @return 回款分页
- */
- PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO);
-
- /**
- * 获得待审核回款数量
- *
- * @param userId 用户编号
- * @return 待审批数量
- */
- Long getAuditReceivableCount(Long userId);
-
- /**
- * 获得合同已回款金额 Map
- *
- * @param contractIds 合同编号
- * @return 回款金额 Map
- */
- Map getReceivablePriceMapByContractId(Collection contractIds);
-
- /**
- * 根据合同编号查询回款数量
- *
- * @param contractId 合同编号
- * @return 回款数量
- */
- Long getReceivableCountByContractId(Long contractId);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
deleted file mode 100644
index 4bf0497..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.receivable.listener;
-
-import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEvent;
-import cn.iocoder.yudao.module.bpm.event.BpmProcessInstanceStatusEventListener;
-import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableService;
-import cn.iocoder.yudao.module.crm.service.receivable.CrmReceivableServiceImpl;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Component;
-
-/**
- * 回款审批的结果的监听器实现类
- *
- * @author HUIHUI
- */
-@Component
-public class CrmReceivableStatusListener extends BpmProcessInstanceStatusEventListener {
-
- @Resource
- private CrmReceivableService receivableService;
-
- @Override
- public String getProcessDefinitionKey() {
- return CrmReceivableServiceImpl.BPM_PROCESS_DEFINITION_KEY;
- }
-
- @Override
- public void onEvent(BpmProcessInstanceStatusEvent event) {
- receivableService.updateReceivableAuditStatus(Long.parseLong(event.getBusinessKey()), event.getStatus());
- }
-
-}
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
deleted file mode 100644
index 70c720b..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsCustomerService.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.statistics;
-
-import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.customer.*;
-
-import java.util.List;
-
-/**
- * CRM 客户分析 Service 接口
- *
- * @author dhb52
- */
-public interface CrmStatisticsCustomerService {
-
- /**
- * 总量分析(按日期)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 总量分析(按用户)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 跟进次数分析(按日期)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getFollowUpSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 跟进次数分析(按用户)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getFollowUpSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 客户跟进次数分析(按类型)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getFollowUpSummaryByType(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 获取客户的首次合同、回款信息列表,用于【客户转化率】页面
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getContractSummary(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 公海客户分析(按日期)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getPoolSummaryByDate(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 公海客户分析(按用户)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getPoolSummaryByUser(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 客户成交周期(按日期)
- *
- * 成交周期的定义:客户 customer 在创建出来,到合同 contract 第一次成交的时间差
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerDealCycleByDate(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 客户成交周期(按用户)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerDealCycleByUser(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 客户成交周期(按区域)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerDealCycleByArea(CrmStatisticsCustomerReqVO reqVO);
-
- /**
- * 客户成交周期(按产品)
- *
- * @param reqVO 请求参数
- * @return 统计数据
- */
- List getCustomerDealCycleByProduct(CrmStatisticsCustomerReqVO reqVO);
-
-}
diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java
deleted file mode 100644
index 10458da..0000000
--- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/statistics/CrmStatisticsFunnelService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package cn.iocoder.yudao.module.crm.service.statistics;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.funnel.*;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-
-import java.util.List;
-
-/**
- * CRM 销售漏斗分析 Service
- *
- * @author HUIHUI
- */
-public interface CrmStatisticsFunnelService {
-
- /**
- * 获得销售漏斗数据
- *
- * @param reqVO 请求
- * @return 销售漏斗数据
- */
- CrmStatisticFunnelSummaryRespVO getFunnelSummary(CrmStatisticsFunnelReqVO reqVO);
-
- /**
- * 获得商机结束状态统计
- *
- * @param reqVO 请求
- * @return 商机结束状态统计
- */
- List getBusinessSummaryByEndStatus(CrmStatisticsFunnelReqVO reqVO);
-
- /**
- * 获取新增商机分析(按日期)
- *
- * @param reqVO 请求
- * @return 新增商机分析
- */
- List