Commit ae64a2f0e92baf1791ca528deb3371e38e0d83fb

Authored by “wangming”
1 parent a590db84

feat: 新增拓客统计数据接口,支持按时间和活动过滤

- 新增GetTkStatistics方法,统计拓客相关数据
- 统计指标:拓客人数、邀约人头、预约人头、到店人头、开单人头、开单金额、消费人头、消费金额
- 支持开始时间、结束时间、活动ID过滤(均为可选)
- 采用分步统计提高性能
- 创建TkStatisticsInput和TkStatisticsOutput DTO
- 更新ILqTkjlbService接口
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/TkStatisticsInput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqTkjlb
  4 +{
  5 + /// <summary>
  6 + /// 拓客统计数据输入
  7 + /// </summary>
  8 + public class TkStatisticsInput
  9 + {
  10 + /// <summary>
  11 + /// 开始时间(可选)
  12 + /// </summary>
  13 + public DateTime? StartTime { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 结束时间(可选)
  17 + /// </summary>
  18 + public DateTime? EndTime { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 活动ID(可选)
  22 + /// </summary>
  23 + public string EventId { get; set; }
  24 + }
  25 +}
  26 +
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqTkjlb/TkStatisticsOutput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqTkjlb
  4 +{
  5 + /// <summary>
  6 + /// 拓客统计数据输出
  7 + /// </summary>
  8 + public class TkStatisticsOutput
  9 + {
  10 + /// <summary>
  11 + /// 拓客人数(去重后的人数)
  12 + /// </summary>
  13 + public int TkCount { get; set; }
  14 +
  15 + /// <summary>
  16 + /// 邀约人头(已邀约人数)
  17 + /// </summary>
  18 + public int YaoyCount { get; set; }
  19 +
  20 + /// <summary>
  21 + /// 预约人头(已预约人数)
  22 + /// </summary>
  23 + public int YyCount { get; set; }
  24 +
  25 + /// <summary>
  26 + /// 到店人头(已到店人数)
  27 + /// </summary>
  28 + public int DdCount { get; set; }
  29 +
  30 + /// <summary>
  31 + /// 开单人头(已开单人数)
  32 + /// </summary>
  33 + public int KdCount { get; set; }
  34 +
  35 + /// <summary>
  36 + /// 开单金额
  37 + /// </summary>
  38 + public decimal KdAmount { get; set; }
  39 +
  40 + /// <summary>
  41 + /// 消费人头(已消费人数)
  42 + /// </summary>
  43 + public int XfCount { get; set; }
  44 +
  45 + /// <summary>
  46 + /// 消费金额
  47 + /// </summary>
  48 + public decimal XfAmount { get; set; }
  49 + }
  50 +}
  51 +
... ...
netcore/src/Modularity/Extend/NCC.Extend.Interfaces/ILqTkjlbService.cs
1 1 using System.Threading.Tasks;
  2 +using NCC.Extend.Entitys.Dto.LqTkjlb;
2 3  
3 4 namespace NCC.Extend.Interfaces.LqTkjlb
4 5 {
... ... @@ -15,5 +16,12 @@ namespace NCC.Extend.Interfaces.LqTkjlb
15 16 /// </summary>
16 17 /// <returns></returns>
17 18 Task<dynamic> GetTeamDetail();
  19 +
  20 + /// <summary>
  21 + /// 获取拓客统计数据
  22 + /// </summary>
  23 + /// <param name="input">查询参数</param>
  24 + /// <returns>拓客统计数据</returns>
  25 + Task<TkStatisticsOutput> GetTkStatistics(TkStatisticsInput input);
18 26 }
19 27 }
20 28 \ No newline at end of file
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqTkjlbService.cs
... ... @@ -960,5 +960,159 @@ namespace NCC.Extend.LqTkjlb
960 960 }
961 961 #endregion
962 962  
  963 + #region 拓客统计数据
  964 + /// <summary>
  965 + /// 获取拓客统计数据
  966 + /// </summary>
  967 + /// <remarks>
  968 + /// 统计拓客相关的各项数据,包括拓客人数、邀约人头、预约人头、到店人头、开单人头、开单金额、消费人头、消费金额
  969 + ///
  970 + /// 示例请求:
  971 + /// ```json
  972 + /// {
  973 + /// "startTime": "2025-10-01",
  974 + /// "endTime": "2025-10-31",
  975 + /// "eventId": "活动ID"
  976 + /// }
  977 + /// ```
  978 + ///
  979 + /// 参数说明:
  980 + /// - startTime: 开始时间(可选)
  981 + /// - endTime: 结束时间(可选)
  982 + /// - eventId: 活动ID(可选)
  983 + ///
  984 + /// 返回字段说明:
  985 + /// - TkCount: 拓客人数
  986 + /// - YaoyCount: 邀约人头
  987 + /// - YyCount: 预约人头
  988 + /// - DdCount: 到店人头
  989 + /// - KdCount: 开单人头
  990 + /// - KdAmount: 开单金额
  991 + /// - XfCount: 消费人头
  992 + /// - XfAmount: 消费金额
  993 + /// </remarks>
  994 + /// <param name="input">查询参数</param>
  995 + /// <returns>拓客统计数据</returns>
  996 + /// <response code="200">成功返回统计数据</response>
  997 + /// <response code="400">参数错误</response>
  998 + /// <response code="500">服务器内部错误</response>
  999 + [HttpPost("get-tk-statistics")]
  1000 + public async Task<TkStatisticsOutput> GetTkStatistics(TkStatisticsInput input)
  1001 + {
  1002 + try
  1003 + {
  1004 + // 构建基本过滤条件
  1005 + string timeFilter = "";
  1006 + if (input.StartTime.HasValue && input.EndTime.HasValue)
  1007 + {
  1008 + timeFilter = $@"
  1009 + AND tk.F_CreateTime >= '{input.StartTime:yyyy-MM-dd HH:mm:ss}'
  1010 + AND tk.F_CreateTime <= '{input.EndTime:yyyy-MM-dd HH:mm:ss}'";
  1011 + }
  1012 + else if (input.StartTime.HasValue)
  1013 + {
  1014 + timeFilter = $"AND tk.F_CreateTime >= '{input.StartTime:yyyy-MM-dd HH:mm:ss}'";
  1015 + }
  1016 + else if (input.EndTime.HasValue)
  1017 + {
  1018 + timeFilter = $"AND tk.F_CreateTime <= '{input.EndTime:yyyy-MM-dd HH:mm:ss}'";
  1019 + }
  1020 +
  1021 + string eventFilter = "";
  1022 + if (!string.IsNullOrWhiteSpace(input.EventId))
  1023 + {
  1024 + eventFilter = $"AND tk.F_EventId = '{input.EventId}'";
  1025 + }
  1026 +
  1027 + // 第一步:获取拓客人数(去重会员ID)
  1028 + var tkSql = $@"
  1029 + SELECT COUNT(DISTINCT tk.F_MemberId) as tk_count
  1030 + FROM lq_tkjlb tk
  1031 + WHERE 1=1 {timeFilter} {eventFilter}";
  1032 +
  1033 + var tkResult = await _db.Ado.SqlQueryAsync<dynamic>(tkSql);
  1034 + var tkCount = Convert.ToInt32(tkResult?.FirstOrDefault()?.tk_count ?? 0);
  1035 +
  1036 + // 第二步:获取邀约人头(去重会员ID)
  1037 + var yaoySql = $@"
  1038 + SELECT COUNT(DISTINCT tk.F_MemberId) as yaoy_count
  1039 + FROM lq_tkjlb tk
  1040 + INNER JOIN lq_yaoyjl yy ON tk.F_MemberId = yy.yykh
  1041 + AND yy.F_StoreId = tk.F_StoreId
  1042 + WHERE 1=1 {timeFilter} {eventFilter}";
  1043 +
  1044 + var yaoyResult = await _db.Ado.SqlQueryAsync<dynamic>(yaoySql);
  1045 + var yaoyCount = Convert.ToInt32(yaoyResult?.FirstOrDefault()?.yaoy_count ?? 0);
  1046 +
  1047 + // 第三步:获取预约人头(去重会员ID)
  1048 + var yySql = $@"
  1049 + SELECT COUNT(DISTINCT tk.F_MemberId) as yy_count
  1050 + FROM lq_tkjlb tk
  1051 + INNER JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk
  1052 + AND yyjl.F_Status = '已确认'
  1053 + WHERE 1=1 {timeFilter} {eventFilter}";
  1054 +
  1055 + var yyResult = await _db.Ado.SqlQueryAsync<dynamic>(yySql);
  1056 + var yyCount = Convert.ToInt32(yyResult?.FirstOrDefault()?.yy_count ?? 0);
  1057 +
  1058 + // 第四步:获取到店人头(预约且状态为已确认,假设预约表有到店时间字段)
  1059 + var ddSql = $@"
  1060 + SELECT COUNT(DISTINCT tk.F_MemberId) as dd_count
  1061 + FROM lq_tkjlb tk
  1062 + INNER JOIN lq_yyjl yyjl ON tk.F_MemberId = yyjl.gk
  1063 + AND yyjl.F_Status = '已确认'
  1064 + WHERE yyjl.yysj <= NOW()
  1065 + AND 1=1 {timeFilter} {eventFilter}";
  1066 +
  1067 + var ddResult = await _db.Ado.SqlQueryAsync<dynamic>(ddSql);
  1068 + var ddCount = Convert.ToInt32(ddResult?.FirstOrDefault()?.dd_count ?? 0);
  1069 +
  1070 + // 第五步:获取开单人头和金额(去重会员ID,金额累加)
  1071 + var kdSql = $@"
  1072 + SELECT
  1073 + COUNT(DISTINCT tk.F_MemberId) as kd_count,
  1074 + COALESCE(SUM(kd.sfyj), 0) as kd_amount
  1075 + FROM lq_tkjlb tk
  1076 + INNER JOIN lq_kd_kdjlb kd ON tk.F_MemberId = kd.kdhy
  1077 + AND kd.F_IsEffective = 1
  1078 + WHERE 1=1 {timeFilter} {eventFilter}";
  1079 +
  1080 + var kdResult = await _db.Ado.SqlQueryAsync<dynamic>(kdSql);
  1081 + var kdCount = Convert.ToInt32(kdResult?.FirstOrDefault()?.kd_count ?? 0);
  1082 + var kdAmount = Convert.ToDecimal(kdResult?.FirstOrDefault()?.kd_amount ?? 0);
  1083 +
  1084 + // 第六步:获取消费人头和金额(去重会员ID,金额累加)
  1085 + var xfSql = $@"
  1086 + SELECT
  1087 + COUNT(DISTINCT tk.F_MemberId) as xf_count,
  1088 + COALESCE(SUM(xh.xfje), 0) as xf_amount
  1089 + FROM lq_tkjlb tk
  1090 + INNER JOIN lq_xh_hyhk xh ON tk.F_MemberId = xh.hy
  1091 + AND xh.F_IsEffective = 1
  1092 + WHERE 1=1 {timeFilter} {eventFilter}";
  1093 +
  1094 + var xfResult = await _db.Ado.SqlQueryAsync<dynamic>(xfSql);
  1095 + var xfCount = Convert.ToInt32(xfResult?.FirstOrDefault()?.xf_count ?? 0);
  1096 + var xfAmount = Convert.ToDecimal(xfResult?.FirstOrDefault()?.xf_amount ?? 0);
  1097 +
  1098 + return new TkStatisticsOutput
  1099 + {
  1100 + TkCount = tkCount,
  1101 + YaoyCount = yaoyCount,
  1102 + YyCount = yyCount,
  1103 + DdCount = ddCount,
  1104 + KdCount = kdCount,
  1105 + KdAmount = kdAmount,
  1106 + XfCount = xfCount,
  1107 + XfAmount = xfAmount
  1108 + };
  1109 + }
  1110 + catch (Exception ex)
  1111 + {
  1112 + throw NCCException.Oh($"获取拓客统计数据失败: {ex.Message}");
  1113 + }
  1114 + }
  1115 + #endregion
  1116 +
963 1117 }
964 1118 }
... ...