diff --git a/.DS_Store b/.DS_Store
index 415fb3b..7966048 100644
--- a/.DS_Store
+++ b/.DS_Store
diff --git a/创建事业部业绩统计流水表视图.sql b/[已用]创建事业部业绩统计流水表视图.sql
index db0e47a..7b7c2c1 100644
--- a/创建事业部业绩统计流水表视图.sql
+++ b/[已用]创建事业部业绩统计流水表视图.sql
@@ -1,20 +1,20 @@
-- 创建事业部业绩统计流水表视图
--- 统计各个事业部的目标业绩、完成业绩、完成率
+-- 统计各个事业部的目标业绩、完成业绩、完成率(基于开卡记录)
DROP VIEW IF EXISTS `v_department_performance_flow`;
CREATE VIEW `v_department_performance_flow` AS
SELECT
+ kd.F_Id AS order_id, -- 开单ID
o.F_Id AS department_id, -- 部门ID
o.F_FullName AS department_name, -- 部门名称
o.F_ParentId AS parent_id, -- 上级部门ID
parent.F_FullName AS parent_name, -- 上级部门名称
o.F_Category AS department_category, -- 部门分类
- kd.F_Id AS order_id, -- 开单ID
- kd.kdrq AS order_date, -- 开单时间
- kd.djmd AS store_id, -- 开单门店ID
+ kd.djmd AS store_id, -- 门店ID
m.mdbm AS store_code, -- 门店编号
m.dm AS store_name, -- 门店名称
+ kd.kdrq AS order_date, -- 开单时间
m.xsyj AS target_amount, -- 目标业绩(门店生命线)
kd.zdyj AS completed_amount, -- 完成业绩(整单业绩)
kd.sfyj AS actual_amount, -- 实付业绩
@@ -55,4 +55,4 @@ WHERE (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1)
AND kd.kdrq IS NOT NULL; -- 只包含有开单日期的记录
-- 添加视图注释
-ALTER VIEW `v_department_performance_flow` COMMENT = '事业部业绩统计流水表视图 - 统计各事业部目标业绩、完成业绩、完成率等详细信息';
+--ALTER VIEW `v_department_performance_flow` COMMENT = '事业部业绩统计流水表视图 - 统计各事业部目标业绩、完成业绩、完成率等详细信息';
diff --git a/[已用]创建其他部门业绩统计流水表视图.sql b/[已用]创建其他部门业绩统计流水表视图.sql
new file mode 100644
index 0000000..faf97dd
--- /dev/null
+++ b/[已用]创建其他部门业绩统计流水表视图.sql
@@ -0,0 +1,59 @@
+-- 创建其他部门业绩统计流水表视图
+-- 统计教育部、科技部、大项目部的开卡流水记录
+
+DROP VIEW IF EXISTS `v_other_department_performance_flow`;
+
+CREATE VIEW `v_other_department_performance_flow` AS
+SELECT
+ kd.F_Id AS order_id, -- 开单ID
+ o.F_Id AS department_id, -- 部门ID
+ o.F_FullName AS department_name, -- 部门名称
+ o.F_ParentId AS parent_id, -- 上级部门ID
+ parent.F_FullName AS parent_name, -- 上级部门名称
+ o.F_Category AS department_category, -- 部门分类
+ kd.djmd AS store_id, -- 门店ID
+ m.mdbm AS store_code, -- 门店编号
+ m.dm AS store_name, -- 门店名称
+ kd.kdrq AS order_date, -- 开单时间
+ m.xsyj AS target_amount, -- 目标业绩(门店生命线)
+ kd.zdyj AS completed_amount, -- 完成业绩(整单业绩)
+ kd.sfyj AS actual_amount, -- 实付业绩
+ kd.qk AS debt_amount, -- 欠款
+ kd.jsj AS golden_triangle, -- 金三角
+ kd.kdhy AS member_id, -- 开单会员ID
+ kd.kdhyc AS member_name, -- 开单会员名称
+ kd.kdhysjh AS member_phone, -- 开单会员手机号
+ kd.gjlx AS customer_type, -- 顾客类型
+ kd.hgjg AS partner_institution, -- 合作机构
+ kd.fkfs AS payment_method, -- 付款方式
+ kd.khly AS customer_source, -- 客户来源
+ kd.tjr AS referrer, -- 推荐人
+ kd.sfskdd AS is_first_order, -- 是否首开订单
+ kd.jj AS description, -- 简介
+ kd.bz AS remarks, -- 备注
+ kd.F_CreateUser AS create_user, -- 开单用户
+ kd.F_FIleUrl AS file_url, -- 方案其他
+ -- 计算完成率
+ CASE
+ WHEN m.xsyj > 0 THEN ROUND((kd.zdyj / m.xsyj) * 100, 2)
+ ELSE 0
+ END AS completion_rate, -- 完成率(%)
+ -- 时间维度字段
+ YEAR(kd.kdrq) AS order_year, -- 开单年份
+ MONTH(kd.kdrq) AS order_month, -- 开单月份
+ QUARTER(kd.kdrq) AS order_quarter, -- 开单季度
+ DATE(kd.kdrq) AS order_date_only, -- 开单日期(不含时间)
+ -- 使用开单日期作为创建时间
+ kd.kdrq AS create_time, -- 创建时间(使用开单日期)
+ kd.kdrq AS modify_time -- 修改时间(使用开单日期)
+FROM base_organize o
+LEFT JOIN base_organize parent ON o.F_ParentId = parent.F_Id
+LEFT JOIN lq_mdxx m ON (m.jyb = o.F_Id OR m.kjb = o.F_Id OR m.dxmb = o.F_Id)
+LEFT JOIN lq_kd_kdjlb kd ON kd.djmd = m.F_Id
+WHERE (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1)
+ AND o.F_Category = 'department' -- 只统计部门类型
+ AND (o.F_FullName IN ('教育部', '科技部', '大项目部') OR parent.F_FullName IN ('教育部', '科技部', '大项目部')) -- 统计这三个大部门及其子部门
+ AND kd.kdrq IS NOT NULL; -- 只包含有开单日期的记录
+
+-- 添加视图注释
+--ALTER VIEW `v_other_department_performance_flow` COMMENT = '其他部门业绩统计流水表视图 - 统计教育部、科技部、大项目部的开卡流水记录';
diff --git a/[已用]创建经理门店基础信息视图.sql b/[已用]创建经理门店基础信息视图.sql
new file mode 100644
index 0000000..348b052
--- /dev/null
+++ b/[已用]创建经理门店基础信息视图.sql
@@ -0,0 +1,31 @@
+-- 创建经理门店基础信息视图(精简版)
+-- 只包含必要的基础数据,不包含生命线设置
+
+DROP VIEW IF EXISTS v_manager_store_basic;
+
+CREATE VIEW v_manager_store_basic AS
+SELECT
+ u.F_Id AS manager_user_id, -- 使用正确的用户ID字段
+ u.F_RealName AS manager_name,
+ u.F_GW AS manager_position,
+ u.F_OrganizeId AS manager_organize_id,
+ org.F_Id AS business_unit_id,
+ org.F_FullName AS business_unit_name,
+ org.F_ParentId AS parent_organize_id,
+ parent_org.F_FullName AS parent_organize_name,
+ md.F_Id AS store_id,
+ md.mdbm AS store_code,
+ md.dm AS store_name,
+ md.syb AS store_business_unit_id
+FROM BASE_USER u
+INNER JOIN BASE_ORGANIZE org ON u.F_OrganizeId = org.F_Id
+INNER JOIN BASE_ORGANIZE parent_org ON org.F_ParentId = parent_org.F_Id
+INNER JOIN lq_mdxx md ON md.syb = org.F_Id
+WHERE u.F_EnabledMark = 1
+ AND u.F_DeleteMark IS NULL
+ AND org.F_EnabledMark = 1
+ AND org.F_DeleteMark IS NULL
+ AND parent_org.F_EnabledMark = 1
+ AND parent_org.F_DeleteMark IS NULL
+ AND (u.F_GW LIKE '%经理%' OR u.F_GW LIKE '%总经理%')
+ AND parent_org.F_FullName = '事业部';
\ No newline at end of file
diff --git a/netcore/netcore/.DS_Store b/netcore/netcore/.DS_Store
index 5128fb4..8349213 100644
--- a/netcore/netcore/.DS_Store
+++ b/netcore/netcore/.DS_Store
diff --git a/netcore/src/Application/.DS_Store b/netcore/src/Application/.DS_Store
index a094ecd..1f866c2 100644
--- a/netcore/src/Application/.DS_Store
+++ b/netcore/src/Application/.DS_Store
diff --git a/netcore/src/Application/NCC.API/.DS_Store b/netcore/src/Application/NCC.API/.DS_Store
index 4d4d2e7..76012f3 100644
--- a/netcore/src/Application/NCC.API/.DS_Store
+++ b/netcore/src/Application/NCC.API/.DS_Store
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsInput.cs
deleted file mode 100644
index 6349506..0000000
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsInput.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.ComponentModel.DataAnnotations;
-
-namespace NCC.Extend.Entitys.Dto.LqMdxx
-{
- ///
- /// 门店统计查询输入参数
- ///
- public class StoreStatisticsInput
- {
- ///
- /// 查询日期
- ///
- ///
- /// 传入日期格式:2025-9-14
- /// 系统会自动计算本月1号到传入日期的时间范围
- /// 例如传入2025-9-14,则查询范围为2025-9-1到2025-9-14
- ///
- /// 2025-9-14
- [Required(ErrorMessage = "查询日期不能为空")]
- public DateTime QueryDate { get; set; }
- }
-}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsOutput.cs
deleted file mode 100644
index 5b31b94..0000000
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqMdxx/StoreStatisticsOutput.cs
+++ /dev/null
@@ -1,120 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace NCC.Extend.Entitys.Dto.LqMdxx
-{
- ///
- /// 门店统计结果输出
- ///
- public class StoreStatisticsOutput
- {
- ///
- /// 查询开始日期
- ///
- /// 2025-09-01
- public DateTime StartDate { get; set; }
-
- ///
- /// 查询结束日期
- ///
- /// 2025-09-14
- public DateTime EndDate { get; set; }
-
- ///
- /// 门店统计列表
- ///
- public List StoreList { get; set; } = new List();
-
- ///
- /// 汇总统计
- ///
- public StoreSummaryInfo Summary { get; set; } = new StoreSummaryInfo();
- }
-
- ///
- /// 门店统计信息
- ///
- public class StoreStatisticsInfo
- {
- ///
- /// 门店ID
- ///
- /// 123456789
- public string StoreId { get; set; }
-
- ///
- /// 门店编码
- ///
- /// MD001
- public string StoreCode { get; set; }
-
- ///
- /// 门店名称
- ///
- /// 北京朝阳店
- public string StoreName { get; set; }
-
- ///
- /// 员工数量
- ///
- /// 该门店的员工总数
- /// 15
- public int EmployeeCount { get; set; }
-
- ///
- /// 项目数量
- ///
- /// 统计期间该门店耗卡的项目总数
- /// 128
- public decimal ProjectCount { get; set; }
-
- ///
- /// 消耗业绩
- ///
- /// 统计期间该门店耗卡的金额总计
- /// 25680.50
- public decimal ConsumeAmount { get; set; }
-
- ///
- /// 城市
- ///
- /// 北京
- public string City { get; set; }
-
- ///
- /// 事业部
- ///
- /// 华北事业部
- public string BusinessUnit { get; set; }
- }
-
- ///
- /// 汇总统计信息
- ///
- public class StoreSummaryInfo
- {
- ///
- /// 门店总数
- ///
- /// 25
- public int TotalStoreCount { get; set; }
-
- ///
- /// 员工总数
- ///
- /// 365
- public int TotalEmployeeCount { get; set; }
-
- ///
- /// 项目总数
- ///
- /// 2580
- public decimal TotalProjectCount { get; set; }
-
- ///
- /// 消耗业绩总计
- ///
- /// 568920.80
- public decimal TotalConsumeAmount { get; set; }
- }
-}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInfo.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInfo.cs
new file mode 100644
index 0000000..6c656b6
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInfo.cs
@@ -0,0 +1,58 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 事业部业绩统计信息
+ ///
+ public class BusinessUnitStatisticsInfo
+ {
+ ///
+ /// 部门ID
+ ///
+ [Display(Name = "部门ID")]
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ [Display(Name = "部门名称")]
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 父部门ID
+ ///
+ [Display(Name = "父部门ID")]
+ public string ParentId { get; set; }
+
+ ///
+ /// 父部门名称
+ ///
+ [Display(Name = "父部门名称")]
+ public string ParentName { get; set; }
+
+ ///
+ /// 目标业绩总和
+ ///
+ [Display(Name = "目标业绩总和")]
+ public decimal TotalTargetAmount { get; set; }
+
+ ///
+ /// 完成业绩总和
+ ///
+ [Display(Name = "完成业绩总和")]
+ public decimal TotalActualAmount { get; set; }
+
+ ///
+ /// 开单总数量
+ ///
+ [Display(Name = "开单总数量")]
+ public int TotalOrderCount { get; set; }
+
+ ///
+ /// 完成率(%)
+ ///
+ [Display(Name = "完成率")]
+ public decimal CompletionRate { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInput.cs
new file mode 100644
index 0000000..4d81bed
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsInput.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 事业部业绩统计查询输入模型
+ ///
+ public class BusinessUnitStatisticsInput
+ {
+ ///
+ /// 开始日期
+ ///
+ [Required(ErrorMessage = "开始日期不能为空")]
+ [Display(Name = "开始日期")]
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 结束日期
+ ///
+ [Required(ErrorMessage = "结束日期不能为空")]
+ [Display(Name = "结束日期")]
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 事业部ID(可选,不传则查询所有事业部)
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsOutput.cs
new file mode 100644
index 0000000..cfecf55
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/BusinessUnitStatisticsOutput.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 事业部业绩统计输出
+ ///
+ public class BusinessUnitStatisticsOutput
+ {
+ ///
+ /// 事业部业绩统计列表
+ ///
+ public List BusinessUnitList { get; set; } = new List();
+
+ ///
+ /// 总记录数
+ ///
+ public int TotalCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInfo.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInfo.cs
new file mode 100644
index 0000000..f6552b1
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInfo.cs
@@ -0,0 +1,70 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 经理业绩统计信息
+ ///
+ public class ManagerStatisticsInfo
+ {
+ ///
+ /// 经理姓名
+ ///
+ [Display(Name = "经理姓名")]
+ public string ManagerName { get; set; }
+
+ ///
+ /// 经理用户ID
+ ///
+ [Display(Name = "经理用户ID")]
+ public string ManagerUserId { get; set; }
+
+ ///
+ /// 事业部名称
+ ///
+ [Display(Name = "事业部名称")]
+ public string BusinessUnitName { get; set; }
+
+ ///
+ /// 事业部ID
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ [Display(Name = "门店名称")]
+ public string StoreName { get; set; }
+
+ ///
+ /// 门店ID
+ ///
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 目标业绩(生命线1)
+ ///
+ [Display(Name = "目标业绩")]
+ public decimal TargetPerformance { get; set; }
+
+ ///
+ /// 完成业绩
+ ///
+ [Display(Name = "完成业绩")]
+ public decimal ActualPerformance { get; set; }
+
+ ///
+ /// 完成率(%)
+ ///
+ [Display(Name = "完成率")]
+ public decimal CompletionRate { get; set; }
+
+ ///
+ /// 开单数量
+ ///
+ [Display(Name = "开单数量")]
+ public int OrderCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInput.cs
new file mode 100644
index 0000000..7ccd8bd
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsInput.cs
@@ -0,0 +1,38 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 经理业绩统计输入模型
+ ///
+ public class ManagerStatisticsInput
+ {
+ ///
+ /// 查询日期
+ ///
+ [Required(ErrorMessage = "查询日期不能为空")]
+ [Display(Name = "查询日期")]
+ public DateTime QueryDate { get; set; }
+
+ ///
+ /// 开始日期
+ ///
+ [Required(ErrorMessage = "开始日期不能为空")]
+ [Display(Name = "开始日期")]
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 结束日期
+ ///
+ [Required(ErrorMessage = "结束日期不能为空")]
+ [Display(Name = "结束日期")]
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 事业部ID(可选,不传则查询所有事业部)
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsOutput.cs
new file mode 100644
index 0000000..e406219
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerStatisticsOutput.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 经理业绩统计输出
+ ///
+ public class ManagerStatisticsOutput
+ {
+ ///
+ /// 经理统计列表
+ ///
+ public List ManagerList { get; set; } = new List();
+
+ ///
+ /// 总记录数
+ ///
+ public int TotalCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsInfo.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsInfo.cs
new file mode 100644
index 0000000..3300eee
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsInfo.cs
@@ -0,0 +1,64 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 经理业绩汇总统计信息
+ ///
+ public class ManagerSummaryStatisticsInfo
+ {
+ ///
+ /// 经理姓名
+ ///
+ [Display(Name = "经理姓名")]
+ public string ManagerName { get; set; }
+
+ ///
+ /// 经理用户ID
+ ///
+ [Display(Name = "经理用户ID")]
+ public string ManagerUserId { get; set; }
+
+ ///
+ /// 事业部名称
+ ///
+ [Display(Name = "事业部名称")]
+ public string BusinessUnitName { get; set; }
+
+ ///
+ /// 事业部ID
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+
+ ///
+ /// 管理门店数量
+ ///
+ [Display(Name = "管理门店数量")]
+ public int StoreCount { get; set; }
+
+ ///
+ /// 目标业绩总和
+ ///
+ [Display(Name = "目标业绩总和")]
+ public decimal TotalTargetPerformance { get; set; }
+
+ ///
+ /// 完成业绩总和
+ ///
+ [Display(Name = "完成业绩总和")]
+ public decimal TotalActualPerformance { get; set; }
+
+ ///
+ /// 完成率(%)
+ ///
+ [Display(Name = "完成率")]
+ public decimal CompletionRate { get; set; }
+
+ ///
+ /// 开单总数量
+ ///
+ [Display(Name = "开单总数量")]
+ public int TotalOrderCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsOutput.cs
new file mode 100644
index 0000000..c74cf9a
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/ManagerSummaryStatisticsOutput.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 经理业绩汇总统计输出
+ ///
+ public class ManagerSummaryStatisticsOutput
+ {
+ ///
+ /// 经理业绩汇总统计列表
+ ///
+ public List ManagerSummaryList { get; set; } = new List();
+
+ ///
+ /// 总记录数
+ ///
+ public int TotalCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInfo.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInfo.cs
new file mode 100644
index 0000000..5ae06f5
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInfo.cs
@@ -0,0 +1,58 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 其他部门业绩统计信息
+ ///
+ public class OtherDepartmentStatisticsInfo
+ {
+ ///
+ /// 部门ID
+ ///
+ [Display(Name = "部门ID")]
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ [Display(Name = "部门名称")]
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 父部门ID
+ ///
+ [Display(Name = "父部门ID")]
+ public string ParentId { get; set; }
+
+ ///
+ /// 父部门名称
+ ///
+ [Display(Name = "父部门名称")]
+ public string ParentName { get; set; }
+
+ ///
+ /// 目标业绩总和
+ ///
+ [Display(Name = "目标业绩总和")]
+ public decimal TotalTargetAmount { get; set; }
+
+ ///
+ /// 完成业绩总和
+ ///
+ [Display(Name = "完成业绩总和")]
+ public decimal TotalActualAmount { get; set; }
+
+ ///
+ /// 开单总数量
+ ///
+ [Display(Name = "开单总数量")]
+ public int TotalOrderCount { get; set; }
+
+ ///
+ /// 完成率(%)
+ ///
+ [Display(Name = "完成率")]
+ public decimal CompletionRate { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInput.cs
new file mode 100644
index 0000000..7faaa7a
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsInput.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 其他部门业绩统计查询输入模型
+ ///
+ public class OtherDepartmentStatisticsInput
+ {
+ ///
+ /// 开始日期
+ ///
+ [Required(ErrorMessage = "开始日期不能为空")]
+ [Display(Name = "开始日期")]
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 结束日期
+ ///
+ [Required(ErrorMessage = "结束日期不能为空")]
+ [Display(Name = "结束日期")]
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 部门ID(可选,不传则查询所有部门)
+ ///
+ [Display(Name = "部门ID")]
+ public string DepartmentId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsOutput.cs
new file mode 100644
index 0000000..7ca5bd9
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/OtherDepartmentStatisticsOutput.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 其他部门业绩统计输出
+ ///
+ public class OtherDepartmentStatisticsOutput
+ {
+ ///
+ /// 部门统计列表
+ ///
+ public List DepartmentList { get; set; } = new List();
+
+ ///
+ /// 总记录数
+ ///
+ public int TotalCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StorePerformanceOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StorePerformanceOutput.cs
index 9516881..2f372c0 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StorePerformanceOutput.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StorePerformanceOutput.cs
@@ -8,6 +8,12 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
public class StorePerformanceOutput
{
///
+ /// 门店ID
+ ///
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+
+ ///
/// 门店编码
///
[Display(Name = "门店编码")]
@@ -20,6 +26,18 @@ namespace NCC.Extend.Entitys.Dto.LqStatistics
public string StoreName { get; set; }
///
+ /// 事业部ID
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+
+ ///
+ /// 事业部名称
+ ///
+ [Display(Name = "事业部名称")]
+ public string BusinessUnitName { get; set; }
+
+ ///
/// 目标业绩(生命线)
///
[Display(Name = "目标业绩")]
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInfo.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInfo.cs
new file mode 100644
index 0000000..7e60874
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInfo.cs
@@ -0,0 +1,64 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 门店统计信息
+ ///
+ public class StoreStatisticsInfo
+ {
+ ///
+ /// 门店ID
+ ///
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+
+ ///
+ /// 门店名称
+ ///
+ [Display(Name = "门店名称")]
+ public string StoreName { get; set; }
+
+ ///
+ /// 门店编码
+ ///
+ [Display(Name = "门店编码")]
+ public string StoreCode { get; set; }
+
+ ///
+ /// 事业部ID
+ ///
+ [Display(Name = "事业部ID")]
+ public string BusinessUnitId { get; set; }
+
+ ///
+ /// 事业部名称
+ ///
+ [Display(Name = "事业部名称")]
+ public string BusinessUnitName { get; set; }
+
+ ///
+ /// 目标业绩
+ ///
+ [Display(Name = "目标业绩")]
+ public decimal TargetPerformance { get; set; }
+
+ ///
+ /// 完成业绩
+ ///
+ [Display(Name = "完成业绩")]
+ public decimal ActualPerformance { get; set; }
+
+ ///
+ /// 开单数量
+ ///
+ [Display(Name = "开单数量")]
+ public int OrderCount { get; set; }
+
+ ///
+ /// 完成率(%)
+ ///
+ [Display(Name = "完成率")]
+ public decimal CompletionRate { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInput.cs
new file mode 100644
index 0000000..c1f3ff0
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsInput.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 门店统计输入模型
+ ///
+ public class StoreStatisticsInput
+ {
+ ///
+ /// 开始日期
+ ///
+ [Required(ErrorMessage = "开始日期不能为空")]
+ [Display(Name = "开始日期")]
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 结束日期
+ ///
+ [Required(ErrorMessage = "结束日期不能为空")]
+ [Display(Name = "结束日期")]
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 门店ID(可选,不传则查询所有门店)
+ ///
+ [Display(Name = "门店ID")]
+ public string StoreId { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsOutput.cs
new file mode 100644
index 0000000..1ba2863
--- /dev/null
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqStatistics/StoreStatisticsOutput.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace NCC.Extend.Entitys.Dto.LqStatistics
+{
+ ///
+ /// 门店统计输出
+ ///
+ public class StoreStatisticsOutput
+ {
+ ///
+ /// 门店统计列表
+ ///
+ public List StoreList { get; set; } = new List();
+
+ ///
+ /// 总记录数
+ ///
+ public int TotalCount { get; set; }
+ }
+}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStatistics/ILqStatisticsService.cs b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStatistics/ILqStatisticsService.cs
index 3e9f377..04fd1bc 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStatistics/ILqStatisticsService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend.Interfaces/LqStatistics/ILqStatisticsService.cs
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-using NCC.Extend.Entitys.Dto.LqStatistics;
using NCC.Extend.Entitys.Dto.LqMdxx;
+using NCC.Extend.Entitys.Dto.LqStatistics;
namespace NCC.Extend.Interfaces.LqStatistics
{
@@ -22,5 +22,33 @@ namespace NCC.Extend.Interfaces.LqStatistics
/// 查询参数
/// 门店统计结果
Task GetStoreStatistics(StoreStatisticsInput input);
+
+ ///
+ /// 获取事业部业绩统计
+ ///
+ /// 查询参数
+ /// 事业部业绩统计结果
+ Task GetBusinessUnitStatistics(BusinessUnitStatisticsInput input);
+
+ ///
+ /// 获取其他部门业绩统计
+ ///
+ /// 查询参数
+ /// 其他部门业绩统计结果
+ Task GetOtherDepartmentStatistics(OtherDepartmentStatisticsInput input);
+
+ ///
+ /// 获取经理业绩统计
+ ///
+ /// 查询参数
+ /// 经理业绩统计结果
+ Task GetManagerStatistics(ManagerStatisticsInput input);
+
+ ///
+ /// 获取经理业绩汇总统计
+ ///
+ /// 查询参数
+ /// 经理业绩汇总统计结果
+ Task GetManagerSummaryStatistics(ManagerStatisticsInput input);
}
}
diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
index 02eb417..8aa9c86 100644
--- a/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
+++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
@@ -1,22 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using NCC.Common.Core.Manager;
using NCC.Common.Enum;
using NCC.Common.Extension;
using NCC.Common.Filter;
using NCC.Dependency;
using NCC.DynamicApiController;
-using NCC.FriendlyException;
-using NCC.Extend.Interfaces.LqStatistics;
+using NCC.Extend.Entitys.Dto.LqMdxx;
using NCC.Extend.Entitys.Dto.LqStatistics;
-using Microsoft.AspNetCore.Mvc;
-using SqlSugar;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
using NCC.Extend.Entitys.lq_mdxx;
-using NCC.Extend.Entitys.Dto.LqMdxx;
+using NCC.Extend.Entitys.lq_yjmxb;
+using NCC.Extend.Interfaces.LqStatistics;
+using NCC.FriendlyException;
using NCC.System.Entitys.Permission;
-using Microsoft.Extensions.Logging;
+using SqlSugar;
namespace NCC.Extend.LqStatistics
{
@@ -35,10 +36,7 @@ namespace NCC.Extend.LqStatistics
///
/// 初始化一个类型的新实例
///
- public LqStatisticsService(
- ISqlSugarRepository lqMdxxRepository,
- IUserManager userManager,
- ILogger logger)
+ public LqStatisticsService(ISqlSugarRepository lqMdxxRepository, IUserManager userManager, ILogger logger)
{
_lqMdxxRepository = lqMdxxRepository;
_db = _lqMdxxRepository.Context;
@@ -46,173 +44,575 @@ namespace NCC.Extend.LqStatistics
_logger = logger;
}
- #region 获取门店业绩统计列表
+ #region 获取门店业绩统计列表
///
/// 获取门店业绩统计列表
///
- ///
- /// 查询所有门店的目标业绩、完成业绩、完成率等关键指标
- ///
- /// 返回数据包含:
- /// - 门店编码和店名
- /// - 目标业绩(生命线)
- /// - 完成业绩(实付业绩)
- /// - 完成率(百分比)
- /// - 开单数量
- ///
- /// 数据来源:v_store_performance_simple 视图
- ///
/// 门店业绩统计列表
- /// 成功返回门店业绩统计列表
- /// 服务器内部错误
[HttpGet]
public async Task> GetStorePerformanceList()
{
try
{
- var result = await _db.Ado.SqlQueryAsync(
- "SELECT " +
- "store_code AS StoreCode, " +
- "store_name AS StoreName, " +
- "target_performance AS TargetPerformance, " +
- "actual_performance AS ActualPerformance, " +
- "completion_rate AS CompletionRate, " +
- "order_count AS OrderCount " +
- "FROM v_store_performance_simple " +
- "ORDER BY actual_performance DESC");
-
- return result ?? new List();
+ _logger.LogInformation("开始查询门店业绩统计列表");
+
+ var storeList = await _lqMdxxRepository
+ .AsQueryable()
+ .Where(x => x.Status == 1)
+ .Select(x => new StorePerformanceOutput
+ {
+ StoreId = x.Id,
+ StoreName = x.Dm,
+ StoreCode = x.Mdbm,
+ BusinessUnitId = x.Syb,
+ BusinessUnitName = x.Syb,
+ TargetPerformance = x.Xsyj ?? 0,
+ ActualPerformance = 0,
+ CompletionRate = 0,
+ })
+ .ToListAsync();
+
+ _logger.LogInformation("门店业绩统计列表查询完成,返回{Count}条记录", storeList.Count);
+
+ return storeList;
}
catch (Exception ex)
{
- throw NCCException.Oh(ErrorCode.COM1005, ex.Message);
+ _logger.LogError(ex, "查询门店业绩统计列表时发生错误");
+ throw NCCException.Oh("查询门店业绩统计列表失败", ex);
}
}
#endregion
- #region 门店统计信息
+ #region 获取门店统计信息
///
/// 获取门店统计信息
///
+ /// 查询参数
+ /// 门店统计结果
+ [HttpPost("StoreStatistics")]
+ public async Task GetStoreStatistics(StoreStatisticsInput input)
+ {
+ try
+ {
+ _logger.LogInformation("开始查询门店统计信息,查询日期:{StartDate} - {EndDate},门店ID:{StoreId}", input.StartDate, input.EndDate, input.StoreId);
+
+ // 构建查询参数
+ var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
+
+ // 构建WHERE条件
+ var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)";
+
+ if (!string.IsNullOrEmpty(input.StoreId))
+ {
+ whereClause += " AND store_id = @storeId";
+ parameters.Add("@storeId", input.StoreId);
+ }
+
+ // 构建SQL查询
+ var sql =
+ $@"
+ SELECT
+ store_id AS StoreId,
+ store_name AS StoreName,
+ store_code AS StoreCode,
+ business_unit_id AS BusinessUnitId,
+ business_unit_name AS BusinessUnitName,
+ target_performance AS TargetPerformance,
+ SUM(COALESCE(actual_amount, 0)) AS ActualPerformance,
+ COUNT(order_id) AS OrderCount,
+ CASE
+ WHEN target_performance > 0
+ THEN ROUND((SUM(COALESCE(actual_amount, 0)) / target_performance) * 100, 2)
+ ELSE 0
+ END AS CompletionRate
+ FROM v_store_daily_consume_stats
+ {whereClause}
+ GROUP BY
+ store_id,
+ store_name,
+ store_code,
+ business_unit_id,
+ business_unit_name,
+ target_performance
+ ORDER BY ActualPerformance DESC";
+
+ _logger.LogInformation("执行SQL查询:{Sql}", sql);
+ _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
+
+ var results = await _db.Ado.SqlQueryAsync(sql, parameters);
+
+ _logger.LogInformation("查询到门店统计数据数量:{Count}", results.Count);
+
+ // 转换为输出格式
+ var storeList = results
+ .Select(r => new StoreStatisticsInfo
+ {
+ StoreId = r.StoreId?.ToString() ?? "",
+ StoreName = r.StoreName?.ToString() ?? "",
+ StoreCode = r.StoreCode?.ToString() ?? "",
+ BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
+ BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
+ TargetPerformance = Convert.ToDecimal(r.TargetPerformance ?? 0),
+ ActualPerformance = Convert.ToDecimal(r.ActualPerformance ?? 0),
+ OrderCount = Convert.ToInt32(r.OrderCount ?? 0),
+ CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
+ })
+ .ToList();
+
+ _logger.LogInformation("门店统计信息查询完成,返回{Count}条记录", storeList.Count);
+
+ return new StoreStatisticsOutput { StoreList = storeList, TotalCount = storeList.Count };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询门店统计信息时发生错误,查询日期:{StartDate} - {EndDate},门店ID:{StoreId}", input.StartDate, input.EndDate, input.StoreId);
+ throw NCCException.Oh("查询门店统计信息失败", ex);
+ }
+ }
+ #endregion
+
+ #region 获取事业部业绩统计
+ ///
+ /// 获取事业部业绩统计
+ ///
+ /// 查询参数
+ /// 事业部业绩统计结果
+ [HttpPost("BusinessUnitStatistics")]
+ public async Task GetBusinessUnitStatistics(BusinessUnitStatisticsInput input)
+ {
+ try
+ {
+ _logger.LogInformation("开始查询事业部业绩统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
+
+ // 构建查询参数
+ var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
+
+ // 构建WHERE条件
+ var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)";
+
+ if (!string.IsNullOrEmpty(input.BusinessUnitId))
+ {
+ whereClause += " AND department_id = @businessUnitId";
+ parameters.Add("@businessUnitId", input.BusinessUnitId);
+ }
+
+ // 构建SQL查询
+ var sql =
+ $@"
+ SELECT
+ department_id AS DepartmentId,
+ department_name AS DepartmentName,
+ parent_id AS ParentId,
+ parent_name AS ParentName,
+ SUM(COALESCE(target_amount, 0)) AS TotalTargetAmount,
+ SUM(COALESCE(actual_amount, 0)) AS TotalActualAmount,
+ COUNT(order_id) AS TotalOrderCount,
+ CASE
+ WHEN SUM(COALESCE(target_amount, 0)) > 0
+ THEN ROUND((SUM(COALESCE(actual_amount, 0)) / SUM(COALESCE(target_amount, 0))) * 100, 2)
+ ELSE 0
+ END AS CompletionRate
+ FROM v_department_performance_flow
+ {whereClause}
+ GROUP BY
+ department_id,
+ department_name,
+ parent_id,
+ parent_name
+ ORDER BY TotalActualAmount DESC";
+
+ _logger.LogInformation("执行SQL查询:{Sql}", sql);
+ _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
+
+ var results = await _db.Ado.SqlQueryAsync(sql, parameters);
+
+ _logger.LogInformation("查询到事业部业绩数据数量:{Count}", results.Count);
+
+ // 转换为输出格式
+ var businessUnitList = results
+ .Select(r => new BusinessUnitStatisticsInfo
+ {
+ DepartmentId = r.DepartmentId?.ToString() ?? "",
+ DepartmentName = r.DepartmentName?.ToString() ?? "",
+ ParentId = r.ParentId?.ToString() ?? "",
+ ParentName = r.ParentName?.ToString() ?? "",
+ TotalTargetAmount = Convert.ToDecimal(r.TotalTargetAmount ?? 0),
+ TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0),
+ TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
+ CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
+ })
+ .ToList();
+
+ _logger.LogInformation("事业部业绩统计查询完成,返回{Count}条记录", businessUnitList.Count);
+
+ return new BusinessUnitStatisticsOutput { BusinessUnitList = businessUnitList, TotalCount = businessUnitList.Count };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询事业部业绩统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
+ throw NCCException.Oh("查询事业部业绩统计失败", ex);
+ }
+ }
+ #endregion
+
+ #region 获取其他部门业绩统计
+ ///
+ /// 获取其他部门业绩统计
+ ///
+ /// 查询参数
+ /// 其他部门业绩统计结果
+ [HttpPost("OtherDepartmentStatistics")]
+ public async Task GetOtherDepartmentStatistics(OtherDepartmentStatisticsInput input)
+ {
+ try
+ {
+ _logger.LogInformation("开始查询其他部门业绩统计,查询日期:{StartDate} - {EndDate},部门ID:{DepartmentId}", input.StartDate, input.EndDate, input.DepartmentId);
+
+ // 构建查询参数
+ var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
+
+ // 构建WHERE条件
+ var whereClause = "WHERE (order_date >= @startDate AND order_date <= @endDate OR order_date IS NULL)";
+
+ if (!string.IsNullOrEmpty(input.DepartmentId))
+ {
+ whereClause += " AND department_id = @departmentId";
+ parameters.Add("@departmentId", input.DepartmentId);
+ }
+
+ // 构建SQL查询
+ var sql =
+ $@"
+ SELECT
+ department_id AS DepartmentId,
+ department_name AS DepartmentName,
+ parent_id AS ParentId,
+ parent_name AS ParentName,
+ SUM(COALESCE(target_amount, 0)) AS TotalTargetAmount,
+ SUM(COALESCE(actual_amount, 0)) AS TotalActualAmount,
+ COUNT(order_id) AS TotalOrderCount,
+ CASE
+ WHEN SUM(COALESCE(target_amount, 0)) > 0
+ THEN ROUND((SUM(COALESCE(actual_amount, 0)) / SUM(COALESCE(target_amount, 0))) * 100, 2)
+ ELSE 0
+ END AS CompletionRate
+ FROM v_other_department_performance_flow
+ {whereClause}
+ GROUP BY
+ department_id,
+ department_name,
+ parent_id,
+ parent_name
+ ORDER BY TotalActualAmount DESC";
+
+ _logger.LogInformation("执行SQL查询:{Sql}", sql);
+ _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
+
+ var results = await _db.Ado.SqlQueryAsync(sql, parameters);
+
+ _logger.LogInformation("查询到其他部门业绩数据数量:{Count}", results.Count);
+
+ // 转换为输出格式
+ var departmentList = results
+ .Select(r => new OtherDepartmentStatisticsInfo
+ {
+ DepartmentId = r.DepartmentId?.ToString() ?? "",
+ DepartmentName = r.DepartmentName?.ToString() ?? "",
+ ParentId = r.ParentId?.ToString() ?? "",
+ ParentName = r.ParentName?.ToString() ?? "",
+ TotalTargetAmount = Convert.ToDecimal(r.TotalTargetAmount ?? 0),
+ TotalActualAmount = Convert.ToDecimal(r.TotalActualAmount ?? 0),
+ TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
+ CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
+ })
+ .ToList();
+
+ _logger.LogInformation("其他部门业绩统计查询完成,返回{Count}条记录", departmentList.Count);
+
+ return new OtherDepartmentStatisticsOutput { DepartmentList = departmentList, TotalCount = departmentList.Count };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询其他部门业绩统计时发生错误,查询日期:{StartDate} - {EndDate},部门ID:{DepartmentId}", input.StartDate, input.EndDate, input.DepartmentId);
+ throw NCCException.Oh("查询其他部门业绩统计失败", ex);
+ }
+ }
+ #endregion
+
+ #region 获取经理业绩统计
+ ///
+ /// 获取经理业绩统计
+ ///
+ /// 查询参数
+ /// 经理业绩统计结果
+ [HttpPost("ManagerStatistics")]
+ public async Task GetManagerStatistics(ManagerStatisticsInput input)
+ {
+ try
+ {
+ _logger.LogInformation("开始查询经理业绩统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
+
+ // 构建查询参数
+ var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
+
+ // 构建WHERE条件
+ var whereClause = "WHERE (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)";
+
+ if (!string.IsNullOrEmpty(input.BusinessUnitId))
+ {
+ whereClause += " AND basic.business_unit_id = @businessUnitId";
+ parameters.Add("@businessUnitId", input.BusinessUnitId);
+ }
+
+ // 构建SQL查询 - 按经理和门店统计
+ var sql =
+ $@"
+ SELECT
+ basic.manager_user_id AS ManagerUserId,
+ basic.manager_name AS ManagerName,
+ basic.business_unit_id AS BusinessUnitId,
+ basic.business_unit_name AS BusinessUnitName,
+ basic.store_id AS StoreId,
+ basic.store_name AS StoreName,
+ COALESCE(smx.smx1, 0) AS TargetPerformance,
+ SUM(COALESCE(flow.actual_amount, 0)) AS ActualPerformance,
+ COUNT(flow.order_id) AS OrderCount,
+ CASE
+ WHEN COALESCE(smx.smx1, 0) > 0
+ THEN ROUND((SUM(COALESCE(flow.actual_amount, 0)) / COALESCE(smx.smx1, 0)) * 100, 2)
+ ELSE 0
+ END AS CompletionRate
+ FROM v_manager_store_basic basic
+ LEFT JOIN lq_zjl_mdsmxsz smx ON basic.store_id = smx.md_id AND basic.manager_user_id = smx.zjl_userid
+ LEFT JOIN v_department_performance_flow flow ON basic.store_id = flow.store_id
+ {whereClause}
+ GROUP BY
+ basic.manager_user_id,
+ basic.manager_name,
+ basic.business_unit_id,
+ basic.business_unit_name,
+ basic.store_id,
+ basic.store_name,
+ smx.smx1
+ ORDER BY ActualPerformance DESC";
+
+ _logger.LogInformation("执行SQL查询:{Sql}", sql);
+ _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
+
+ var results = await _db.Ado.SqlQueryAsync(sql, parameters);
+
+ _logger.LogInformation("查询到经理业绩数据数量:{Count}", results.Count);
+
+ // 转换为输出格式
+ var managerList = results
+ .Select(r => new ManagerStatisticsInfo
+ {
+ ManagerName = r.ManagerName?.ToString() ?? "",
+ ManagerUserId = r.ManagerUserId?.ToString() ?? "",
+ BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
+ BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
+ StoreName = r.StoreName?.ToString() ?? "",
+ StoreId = r.StoreId?.ToString() ?? "",
+ TargetPerformance = Convert.ToDecimal(r.TargetPerformance ?? 0),
+ ActualPerformance = Convert.ToDecimal(r.ActualPerformance ?? 0),
+ OrderCount = Convert.ToInt32(r.OrderCount ?? 0),
+ CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
+ })
+ .ToList();
+
+ _logger.LogInformation("经理业绩统计查询完成,返回{Count}条记录", managerList.Count);
+
+ return new ManagerStatisticsOutput { ManagerList = managerList, TotalCount = managerList.Count };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询经理业绩统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
+ throw NCCException.Oh("查询经理业绩统计失败", ex);
+ }
+ }
+ #endregion
+
+ #region 获取经理业绩汇总统计
+ ///
+ /// 获取经理业绩汇总统计
+ ///
///
- /// 统计各个门店在员工数量、项目数(耗卡里面的项目数量)和消耗业绩(耗卡里面的金额)
- /// 可以传入日期,然后去统计本月一号到传入的日期
- ///
+ /// 统计每个经理的目标业绩总和、完成业绩总和、完成率等汇总信息
+ ///
/// 示例请求:
/// ```json
/// {
- /// "queryDate": "2025-09-14"
+ /// "startDate": "2025-01-01T00:00:00",
+ /// "endDate": "2025-01-31T23:59:59",
+ /// "businessUnitId": "事业部ID(可选)"
/// }
/// ```
- ///
+ ///
/// 参数说明:
- /// - queryDate: 查询日期,系统会自动计算本月1号到该日期的统计范围
+ /// - startDate: 开始日期,格式:yyyy-MM-ddTHH:mm:ss
+ /// - endDate: 结束日期,格式:yyyy-MM-ddTHH:mm:ss
+ /// - businessUnitId: 事业部ID,可选参数,不传则查询所有事业部
+ ///
+ /// 返回数据说明:
+ /// - ManagerName: 经理姓名
+ /// - ManagerUserId: 经理用户ID
+ /// - BusinessUnitName: 事业部名称
+ /// - BusinessUnitId: 事业部ID
+ /// - StoreCount: 管理门店数量
+ /// - TotalTargetPerformance: 目标业绩总和
+ /// - TotalActualPerformance: 完成业绩总和
+ /// - CompletionRate: 完成率(%)
+ /// - TotalOrderCount: 开单总数量
///
/// 查询参数
- /// 门店统计结果
- /// 查询成功
- /// 参数错误
+ /// 经理业绩汇总统计结果
+ /// 成功返回经理业绩汇总统计数据
+ /// 请求参数错误
/// 服务器内部错误
- [HttpPost("StoreStatistics")]
- public async Task GetStoreStatistics([FromBody] StoreStatisticsInput input)
+ [HttpPost("ManagerSummaryStatistics")]
+ public async Task GetManagerSummaryStatistics(ManagerStatisticsInput input)
{
try
{
- _logger.LogInformation("开始查询门店统计信息,查询日期:{QueryDate}", input.QueryDate);
-
- // 计算查询时间范围:本月1号到传入日期
- var startDate = new DateTime(input.QueryDate.Year, input.QueryDate.Month, 1);
- var endDate = input.QueryDate.Date.AddDays(1).AddSeconds(-1); // 包含当天结束时间
+ _logger.LogInformation("开始查询经理业绩汇总统计,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
- _logger.LogInformation("统计时间范围:{StartDate} 到 {EndDate}", startDate, endDate);
+ // 构建查询参数
+ var parameters = new Dictionary { { "@startDate", input.StartDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", input.EndDate.ToString("yyyy-MM-dd 23:59:59") } };
- // 1. 查询门店基础信息
- var storeList = await _db.Queryable()
- .Select(it => new StoreStatisticsInfo
- {
- StoreId = it.Id,
- StoreCode = it.Mdbm,
- StoreName = it.Dm,
- City = it.Cs,
- BusinessUnit = it.Syb,
- EmployeeCount = 0,
- ProjectCount = 0,
- ConsumeAmount = 0
- })
- .ToListAsync();
+ // 构建WHERE条件
+ var whereClause = "WHERE (flow.order_date >= @startDate AND flow.order_date <= @endDate OR flow.order_date IS NULL)";
- _logger.LogInformation("查询到门店数量:{Count}", storeList.Count);
+ if (!string.IsNullOrEmpty(input.BusinessUnitId))
+ {
+ whereClause += " AND basic.business_unit_id = @businessUnitId";
+ parameters.Add("@businessUnitId", input.BusinessUnitId);
+ }
- // 2. 查询员工数量(按门店统计)
- var employeeCounts = await _db.Queryable()
- .Where(u => !string.IsNullOrEmpty(u.Mdid) && u.DeleteMark != 1)
- .GroupBy(u => u.Mdid)
- .Select(g => new { StoreId = g.Mdid, Count = SqlFunc.AggregateCount(g.Id) })
- .ToListAsync();
+ // 构建SQL查询 - 按经理汇总统计
+ var sql =
+ $@"
+ SELECT
+ basic.manager_user_id AS ManagerUserId,
+ basic.manager_name AS ManagerName,
+ basic.business_unit_id AS BusinessUnitId,
+ basic.business_unit_name AS BusinessUnitName,
+ COUNT(DISTINCT basic.store_id) AS StoreCount,
+ SUM(COALESCE(smx.smx1, 0)) AS TotalTargetPerformance,
+ SUM(COALESCE(flow.actual_amount, 0)) AS TotalActualPerformance,
+ COUNT(flow.order_id) AS TotalOrderCount,
+ CASE
+ WHEN SUM(COALESCE(smx.smx1, 0)) > 0
+ THEN ROUND((SUM(COALESCE(flow.actual_amount, 0)) / SUM(COALESCE(smx.smx1, 0))) * 100, 2)
+ ELSE 0
+ END AS CompletionRate
+ FROM v_manager_store_basic basic
+ LEFT JOIN lq_zjl_mdsmxsz smx ON basic.store_id = smx.md_id AND basic.manager_user_id = smx.zjl_userid
+ LEFT JOIN v_department_performance_flow flow ON basic.store_id = flow.store_id
+ {whereClause}
+ GROUP BY
+ basic.manager_user_id,
+ basic.manager_name,
+ basic.business_unit_id,
+ basic.business_unit_name
+ ORDER BY TotalActualPerformance DESC";
- _logger.LogInformation("查询到员工统计数量:{Count}", employeeCounts.Count);
+ _logger.LogInformation("执行SQL查询:{Sql}", sql);
+ _logger.LogInformation("查询参数:{Parameters}", string.Join(", ", parameters.Select(p => $"{p.Key}={p.Value}")));
- // 3. 从视图查询项目数和消耗业绩
- var consumeStats = await _db.SqlQueryable(@"
- SELECT
- store_id,
- SUM(total_project_count) as total_project_count,
- SUM(total_consume_amount) as total_consume_amount
- FROM v_store_daily_consume_stats
- WHERE consume_date >= @startDate AND consume_date <= @endDate
- GROUP BY store_id")
- .AddParameters(new { startDate = startDate.ToString("yyyy-MM-dd"), endDate = input.QueryDate.ToString("yyyy-MM-dd") })
- .ToListAsync();
+ var results = await _db.Ado.SqlQueryAsync(sql, parameters);
- _logger.LogInformation("查询到消耗统计数量:{Count}", consumeStats.Count);
+ _logger.LogInformation("查询到经理业绩汇总数据数量:{Count}", results.Count);
- // 4. 合并统计数据
- foreach (var store in storeList)
- {
- // 匹配员工数量
- var employeeCount = employeeCounts.FirstOrDefault(e => e.StoreId == store.StoreId);
- if (employeeCount != null)
+ // 转换为输出格式
+ var managerSummaryList = results
+ .Select(r => new ManagerSummaryStatisticsInfo
{
- store.EmployeeCount = employeeCount.Count;
- }
+ ManagerName = r.ManagerName?.ToString() ?? "",
+ ManagerUserId = r.ManagerUserId?.ToString() ?? "",
+ BusinessUnitName = r.BusinessUnitName?.ToString() ?? "",
+ BusinessUnitId = r.BusinessUnitId?.ToString() ?? "",
+ StoreCount = Convert.ToInt32(r.StoreCount ?? 0),
+ TotalTargetPerformance = Convert.ToDecimal(r.TotalTargetPerformance ?? 0),
+ TotalActualPerformance = Convert.ToDecimal(r.TotalActualPerformance ?? 0),
+ TotalOrderCount = Convert.ToInt32(r.TotalOrderCount ?? 0),
+ CompletionRate = Convert.ToDecimal(r.CompletionRate ?? 0),
+ })
+ .ToList();
+
+ _logger.LogInformation("经理业绩汇总统计查询完成,返回{Count}条记录", managerSummaryList.Count);
+
+ return new ManagerSummaryStatisticsOutput { ManagerSummaryList = managerSummaryList, TotalCount = managerSummaryList.Count };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "查询经理业绩汇总统计时发生错误,查询日期:{StartDate} - {EndDate},事业部ID:{BusinessUnitId}", input.StartDate, input.EndDate, input.BusinessUnitId);
+ throw NCCException.Oh("查询经理业绩汇总统计失败", ex);
+ }
+ }
+ #endregion
- // 匹配项目数和消耗业绩
- var consumeStat = consumeStats.FirstOrDefault(c => c.store_id?.ToString() == store.StoreId);
- if (consumeStat != null)
+ #region 私有方法
+ ///
+ /// 递归获取子部门列表
+ ///
+ /// 父部门ID
+ /// 子部门列表
+ private async Task> GetSubDepartmentsRecursively(string parentId)
+ {
+ var subDepartments = new List();
+
+ try
+ {
+ // 查询直接子部门
+ var directChildren = await _db.Queryable()
+ .Where(x => x.ParentId == parentId && x.EnabledMark == 1 && x.DeleteMark == null)
+ .Select(x => new DepartmentInfo
{
- store.ProjectCount = Convert.ToDecimal(consumeStat.total_project_count ?? 0);
- store.ConsumeAmount = Convert.ToDecimal(consumeStat.total_consume_amount ?? 0);
- }
- }
+ DepartmentId = x.Id,
+ DepartmentName = x.FullName,
+ ParentId = x.ParentId,
+ })
+ .ToListAsync();
- // 5. 计算汇总统计
- var summary = new StoreSummaryInfo
- {
- TotalStoreCount = storeList.Count,
- TotalEmployeeCount = storeList.Sum(s => s.EmployeeCount),
- TotalProjectCount = storeList.Sum(s => s.ProjectCount),
- TotalConsumeAmount = storeList.Sum(s => s.ConsumeAmount)
- };
+ subDepartments.AddRange(directChildren);
- var result = new StoreStatisticsOutput
+ // 递归查询每个子部门的子部门
+ foreach (var child in directChildren)
{
- StartDate = startDate,
- EndDate = input.QueryDate,
- StoreList = storeList.OrderByDescending(s => s.ConsumeAmount).ToList(),
- Summary = summary
- };
-
- _logger.LogInformation("门店统计查询完成,门店数:{StoreCount},总员工数:{EmployeeCount},总项目数:{ProjectCount},总消耗业绩:{ConsumeAmount}",
- summary.TotalStoreCount, summary.TotalEmployeeCount, summary.TotalProjectCount, summary.TotalConsumeAmount);
+ var grandChildren = await GetSubDepartmentsRecursively(child.DepartmentId);
+ subDepartments.AddRange(grandChildren);
+ }
- return result;
+ return subDepartments;
}
catch (Exception ex)
{
- _logger.LogError(ex, "查询门店统计信息时发生错误,查询日期:{QueryDate}", input.QueryDate);
- throw NCCException.Oh(ErrorCode.COM1000, "查询门店统计信息失败");
+ _logger.LogError(ex, "递归获取子部门列表时发生错误,父部门ID:{ParentId}", parentId);
+ return subDepartments;
}
}
#endregion
}
+
+ ///
+ /// 部门信息
+ ///
+ public class DepartmentInfo
+ {
+ ///
+ /// 部门ID
+ ///
+ public string DepartmentId { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 父部门ID
+ ///
+ public string ParentId { get; set; }
+ }
}
diff --git a/创建经理门店业绩统计视图.sql b/创建经理门店业绩统计视图.sql
new file mode 100644
index 0000000..c26f5ce
--- /dev/null
+++ b/创建经理门店业绩统计视图.sql
@@ -0,0 +1,87 @@
+-- 创建经理门店业绩统计视图
+-- 融合经理信息、管理门店、生命线设置、业绩流水数据
+
+DROP VIEW IF EXISTS `v_manager_store_performance`;
+
+CREATE VIEW `v_manager_store_performance` AS
+SELECT
+ -- 经理基础信息
+ u.F_Id AS manager_user_id, -- 经理用户ID
+ u.F_REALNAME AS manager_name, -- 经理姓名
+ u.F_GW AS manager_position, -- 经理岗位
+ u.F_ORGANIZEID AS manager_organize_id, -- 经理组织ID
+
+ -- 事业部信息
+ o.F_Id AS business_unit_id, -- 事业部ID
+ o.F_FullName AS business_unit_name, -- 事业部名称
+ o.F_ParentId AS parent_organize_id, -- 上级组织ID
+ parent.F_FullName AS parent_organize_name, -- 上级组织名称
+
+ -- 门店信息
+ md.F_Id AS store_id, -- 门店ID
+ md.mdbm AS store_code, -- 门店编号
+ md.dm AS store_name, -- 门店名称
+ md.syb AS store_business_unit_id, -- 门店所属事业部ID
+
+ -- 生命线设置信息
+ COALESCE(zjl.smx1, 0) AS target_performance, -- 目标业绩(生命线1)
+ zjl.tcbl1 AS commission_rate1, -- 生命线1提成比例
+ zjl.smx2 AS target_performance2, -- 目标业绩2(生命线2)
+ zjl.tcbl2 AS commission_rate2, -- 生命线2提成比例
+ zjl.smx3 AS target_performance3, -- 目标业绩3(生命线3)
+ zjl.tcbl3 AS commission_rate3, -- 生命线3提成比例
+
+ -- 业绩流水信息(从现有视图获取)
+ flow.order_id, -- 开单ID
+ flow.order_date, -- 开单时间
+ flow.completed_amount, -- 完成业绩(整单业绩)
+ flow.actual_amount, -- 实付业绩
+ flow.debt_amount, -- 欠款
+ flow.completion_rate, -- 完成率
+ flow.golden_triangle, -- 金三角
+ flow.member_id, -- 开单会员ID
+ flow.member_name, -- 开单会员名称
+ flow.member_phone, -- 开单会员手机号
+ flow.customer_type, -- 顾客类型
+ flow.payment_method, -- 付款方式
+ flow.customer_source, -- 客户来源
+
+ -- 时间维度
+ flow.order_year, -- 开单年份
+ flow.order_month, -- 开单月份
+ flow.order_quarter, -- 开单季度
+ flow.order_date_only, -- 开单日期(不含时间)
+
+ -- 统计标识
+ CASE
+ WHEN flow.order_id IS NOT NULL THEN 1
+ ELSE 0
+ END AS has_performance, -- 是否有业绩记录
+
+ -- 创建时间
+ COALESCE(flow.create_time, NOW()) AS create_time,
+ COALESCE(flow.modify_time, NOW()) AS modify_time
+
+FROM base_user u
+-- 关联组织信息
+LEFT JOIN base_organize o ON u.F_ORGANIZEID = o.F_Id
+LEFT JOIN base_organize parent ON o.F_ParentId = parent.F_Id
+-- 关联门店信息(通过事业部关联)
+LEFT JOIN lq_mdxx md ON md.syb = o.F_Id
+-- 关联生命线设置
+LEFT JOIN lq_zjl_mdsmxsz zjl ON zjl.zjl_userid = u.F_Id
+ AND zjl.md_id = md.F_Id
+ AND zjl.deletemark = 0
+-- 关联业绩流水(从现有视图)
+LEFT JOIN v_department_performance_flow flow ON flow.store_id = md.F_Id
+ AND flow.department_id = o.F_Id
+
+WHERE u.F_DELETEMARK IS NULL -- 用户未删除
+ AND u.F_GW IS NOT NULL -- 有岗位信息
+ AND (u.F_GW LIKE '%经理%' OR u.F_GW LIKE '%总经理%' OR u.F_GW LIKE '%主管%') -- 经理岗位
+ AND o.F_Category = 'department' -- 部门类型
+ AND (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1) -- 组织未删除
+ AND md.F_Id IS NOT NULL; -- 有门店信息
+
+-- 添加视图注释
+--ALTER VIEW `v_manager_store_performance` COMMENT = '经理门店业绩统计视图 - 融合经理信息、管理门店、生命线设置、业绩流水数据';