Commit 11b81187f08d8f74392574e06d24dd7e77a61d59

Authored by “wangming”
1 parent 6b697cd3

feat: 优化业绩统计逻辑,按部门ID去重累加完成业绩;添加事业部名称排序功能;更新门店品项统计返回结构,支持层级展示

netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqPackageInfo/ActivityStatisticsByStoreItemOutput.cs
... ... @@ -18,15 +18,15 @@ namespace NCC.Extend.Entitys.Dto.LqPackageInfo
18 18 public string ActivityName { get; set; }
19 19  
20 20 /// <summary>
21   - /// 门店品项统计列表
  21 + /// 门店统计列表(层级结构:每个门店下包含品项列表)
22 22 /// </summary>
23   - public List<StoreItemStatisticsItem> StoreItemList { get; set; }
  23 + public List<StoreStatisticsWithItems> StoreList { get; set; }
24 24 }
25 25  
26 26 /// <summary>
27   - /// 门店品项统计项
  27 + /// 门店统计(包含品项列表)
28 28 /// </summary>
29   - public class StoreItemStatisticsItem
  29 + public class StoreStatisticsWithItems
30 30 {
31 31 /// <summary>
32 32 /// 门店ID
... ... @@ -39,6 +39,17 @@ namespace NCC.Extend.Entitys.Dto.LqPackageInfo
39 39 public string StoreName { get; set; }
40 40  
41 41 /// <summary>
  42 + /// 该门店下的品项统计列表
  43 + /// </summary>
  44 + public List<StoreItemStatisticsItem> ItemList { get; set; }
  45 + }
  46 +
  47 + /// <summary>
  48 + /// 门店品项统计项
  49 + /// </summary>
  50 + public class StoreItemStatisticsItem
  51 + {
  52 + /// <summary>
42 53 /// 品项ID
43 54 /// </summary>
44 55 public string ItemId { get; set; }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
... ... @@ -13,6 +13,7 @@ using System;
13 13 using System.Collections.Generic;
14 14 using System.Linq;
15 15 using System.Text;
  16 +using System.Text.RegularExpressions;
16 17 using System.Threading.Tasks;
17 18 using Yitter.IdGenerator;
18 19 using NCC.Common.Helper;
... ... @@ -529,48 +530,39 @@ namespace NCC.Extend
529 530 return new List<TianwangGroupPerformanceCompletionOutput>();
530 531 }
531 532  
532   - // 第二步:统计各天王团的完成业绩(分类型统计)
533   - var completedPerformanceDataList = new List<dynamic>();
  533 + // 第二步:统计各天王团的完成业绩(直接按部门ID统计,避免重复计算)
  534 + var deptIdsStrForQuery = string.Join("','", departmentDict.Keys);
534 535  
535   - foreach (var deptType in tianwangDepartments)
536   - {
537   - var deptIdsStrForQuery = string.Join("','", departmentDict.Keys);
538   -
539   - var completedPerformanceSql = $@"
540   - SELECT
541   - o.F_Id as DepartmentId,
542   - COALESCE(SUM(billing.sfyj), 0) as CompletedPerformance
543   - FROM lq_kd_kdjlb billing
544   - INNER JOIN lq_mdxx store ON billing.djmd = store.F_Id
545   - INNER JOIN base_organize o ON store.{deptType.Key} = o.F_Id
546   - WHERE billing.F_IsEffective = 1
547   - AND o.F_Category = 'department'
548   - AND (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1)
549   - AND DATE(billing.kdrq) >= '{startDate:yyyy-MM-dd}'
550   - AND DATE(billing.kdrq) <= '{endDate:yyyy-MM-dd}'
551   - AND o.F_Id IN ('{deptIdsStrForQuery}')
552   - GROUP BY o.F_Id";
  536 + // 使用 OR 条件连接三个部门类型字段,确保每个开单记录只被统计一次到对应的部门
  537 + var completedPerformanceSql = $@"
  538 + SELECT
  539 + o.F_Id as DepartmentId,
  540 + COALESCE(SUM(billing.sfyj), 0) as CompletedPerformance
  541 + FROM lq_kd_kdjlb billing
  542 + INNER JOIN lq_mdxx store ON billing.djmd = store.F_Id
  543 + INNER JOIN base_organize o ON (
  544 + (store.jyb = o.F_Id AND o.F_FullName IN ('教育一部', '教育二部'))
  545 + OR (store.kjb = o.F_Id AND o.F_FullName IN ('科技一部', '科技二部'))
  546 + OR (store.dxmb = o.F_Id AND o.F_FullName IN ('大项目一部', '大项目二部'))
  547 + )
  548 + WHERE billing.F_IsEffective = 1
  549 + AND o.F_Category = 'department'
  550 + AND (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1)
  551 + AND DATE(billing.kdrq) >= '{startDate:yyyy-MM-dd}'
  552 + AND DATE(billing.kdrq) <= '{endDate:yyyy-MM-dd}'
  553 + AND o.F_Id IN ('{deptIdsStrForQuery}')
  554 + GROUP BY o.F_Id";
553 555  
554   - var completedPerformanceData = await _db.Ado.SqlQueryAsync<dynamic>(completedPerformanceSql);
555   - if (completedPerformanceData != null)
556   - {
557   - completedPerformanceDataList.AddRange(completedPerformanceData);
558   - }
559   - }
  556 + var completedPerformanceData = await _db.Ado.SqlQueryAsync<dynamic>(completedPerformanceSql);
560 557  
561   - // 第三步:合并数据并计算完成率(按部门ID去重累加)
  558 + // 第三步:将完成业绩数据填充到部门字典中
562 559 var departmentPerformanceDict = new Dictionary<string, decimal>();
563   - foreach (var item in completedPerformanceDataList)
  560 + if (completedPerformanceData != null)
564 561 {
565   - var departmentId = item.DepartmentId.ToString();
566   - var completedPerformance = Convert.ToDecimal(item.CompletedPerformance);
567   -
568   - if (departmentPerformanceDict.ContainsKey(departmentId))
569   - {
570   - departmentPerformanceDict[departmentId] += completedPerformance;
571   - }
572   - else
  562 + foreach (var item in completedPerformanceData)
573 563 {
  564 + var departmentId = item.DepartmentId.ToString();
  565 + var completedPerformance = Convert.ToDecimal(item.CompletedPerformance);
574 566 departmentPerformanceDict[departmentId] = completedPerformance;
575 567 }
576 568 }
... ... @@ -1069,7 +1061,9 @@ namespace NCC.Extend
1069 1061 })
1070 1062 .ToList(),
1071 1063 })
1072   - .OrderBy(x => x.BusinessUnitName) // 按事业部名称排序
  1064 + .ToList()
  1065 + .OrderBy(x => ExtractBusinessUnitNumber(x.BusinessUnitName)) // 按事业部数字排序(事业一部、事业二部...)
  1066 + .ThenBy(x => x.BusinessUnitName) // 如果数字相同,按名称排序
1073 1067 .ToList();
1074 1068  
1075 1069 return result;
... ... @@ -1152,19 +1146,12 @@ namespace NCC.Extend
1152 1146  
1153 1147 // 日期(格式:11月8日)
1154 1148 textBuilder.AppendLine($"{targetDate.Month}月{targetDate.Day}日");
1155   - textBuilder.AppendLine();
1156   -
1157 1149 // 今日总业绩和总单量
1158 1150 textBuilder.AppendLine($"今日总业绩:{totalPerformance:F0}");
1159   - textBuilder.AppendLine();
1160 1151 textBuilder.AppendLine($"今日总单量:{totalOrderCount}");
1161   - textBuilder.AppendLine();
1162   -
1163 1152 // 标语
1164 1153 textBuilder.AppendLine("绿纤人用结果捍卫尊严 ");
1165   - textBuilder.AppendLine();
1166 1154 textBuilder.AppendLine("业绩捷报 ");
1167   - textBuilder.AppendLine();
1168 1155  
1169 1156 // 每个事业部的数据
1170 1157 foreach (var unit in statistics)
... ... @@ -1175,10 +1162,7 @@ namespace NCC.Extend
1175 1162  
1176 1163 // 事业部业绩和单量
1177 1164 textBuilder.AppendLine($"{unit.BusinessUnitName}总业绩:{unit.TotalPerformance:F0}");
1178   - textBuilder.AppendLine();
1179 1165 textBuilder.AppendLine($"{unit.BusinessUnitName}总单量:{unit.TotalOrderCount}");
1180   - textBuilder.AppendLine();
1181   -
1182 1166 // 按门店分组订单
1183 1167 var ordersByStore = unit.Orders
1184 1168 .GroupBy(x => x.StoreName)
... ... @@ -1207,7 +1191,6 @@ namespace NCC.Extend
1207 1191 {
1208 1192 textBuilder.AppendLine($"第{orderIndex}单:{order.StoreName}{teacherNames}{order.Amount:F0}");
1209 1193 }
1210   - textBuilder.AppendLine();
1211 1194 orderIndex++;
1212 1195 }
1213 1196 }
... ... @@ -1220,6 +1203,84 @@ namespace NCC.Extend
1220 1203 throw NCCException.Oh($"获取事业部开单统计文本失败: {ex.Message}", ex);
1221 1204 }
1222 1205 }
  1206 +
  1207 + /// <summary>
  1208 + /// 从事业部名称中提取数字(用于排序)
  1209 + /// 例如:"事业一部" -> 1, "事业二部" -> 2, "事业三部" -> 3
  1210 + /// </summary>
  1211 + /// <param name="businessUnitName">事业部名称</param>
  1212 + /// <returns>提取的数字,如果提取失败返回999(排在最后)</returns>
  1213 + private int ExtractBusinessUnitNumber(string businessUnitName)
  1214 + {
  1215 + if (string.IsNullOrEmpty(businessUnitName))
  1216 + {
  1217 + return 999;
  1218 + }
  1219 +
  1220 + // 使用正则表达式提取数字
  1221 + var match = Regex.Match(businessUnitName, @"[一二三四五六七八九十]+|[\d]+");
  1222 + if (match.Success)
  1223 + {
  1224 + var numberStr = match.Value;
  1225 +
  1226 + // 如果是中文数字,转换为阿拉伯数字
  1227 + if (Regex.IsMatch(numberStr, @"[一二三四五六七八九十]+"))
  1228 + {
  1229 + var chineseNumbers = new Dictionary<string, int>
  1230 + {
  1231 + { "一", 1 }, { "二", 2 }, { "三", 3 }, { "四", 4 }, { "五", 5 },
  1232 + { "六", 6 }, { "七", 7 }, { "八", 8 }, { "九", 9 }, { "十", 10 }
  1233 + };
  1234 +
  1235 + // 处理"十"的情况(如"十一"、"十二"等)
  1236 + if (numberStr == "十")
  1237 + {
  1238 + return 10;
  1239 + }
  1240 + else if (numberStr.StartsWith("十"))
  1241 + {
  1242 + // 十一、十二...十九
  1243 + var remainder = numberStr.Substring(1);
  1244 + if (chineseNumbers.ContainsKey(remainder))
  1245 + {
  1246 + return 10 + chineseNumbers[remainder];
  1247 + }
  1248 + }
  1249 + else if (numberStr.EndsWith("十"))
  1250 + {
  1251 + // 二十、三十...九十
  1252 + var prefix = numberStr.Substring(0, numberStr.Length - 1);
  1253 + if (chineseNumbers.ContainsKey(prefix))
  1254 + {
  1255 + return chineseNumbers[prefix] * 10;
  1256 + }
  1257 + }
  1258 + else if (numberStr.Length == 2 && numberStr.Contains("十"))
  1259 + {
  1260 + // 二十一、二十二...九十九
  1261 + var parts = numberStr.Split('十');
  1262 + if (parts.Length == 2)
  1263 + {
  1264 + var tens = parts[0] == "" ? 1 : (chineseNumbers.ContainsKey(parts[0]) ? chineseNumbers[parts[0]] : 0);
  1265 + var ones = parts[1] == "" ? 0 : (chineseNumbers.ContainsKey(parts[1]) ? chineseNumbers[parts[1]] : 0);
  1266 + return tens * 10 + ones;
  1267 + }
  1268 + }
  1269 + else if (chineseNumbers.ContainsKey(numberStr))
  1270 + {
  1271 + return chineseNumbers[numberStr];
  1272 + }
  1273 + }
  1274 + else if (int.TryParse(numberStr, out var number))
  1275 + {
  1276 + // 如果是阿拉伯数字,直接返回
  1277 + return number;
  1278 + }
  1279 + }
  1280 +
  1281 + // 如果提取失败,返回999(排在最后)
  1282 + return 999;
  1283 + }
1223 1284 #endregion
1224 1285  
1225 1286  
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqPackageInfoService.cs
... ... @@ -901,6 +901,7 @@ namespace NCC.Extend.LqPackageInfo
901 901 }
902 902  
903 903 // 5. 按品项分组统计(先获取基础统计数据)
  904 + // 注意:SqlSugar 的 AggregateSum 可能不支持三元运算符,需要先查询数据再计算
904 905 var itemStatistics = await baseQuery
905 906 .GroupBy((px, kd) => new { ItemId = px.Px, ItemName = px.Pxmc })
906 907 .Select((px, kd) => new
... ... @@ -908,14 +909,25 @@ namespace NCC.Extend.LqPackageInfo
908 909 ItemId = px.Px ?? "",
909 910 ItemName = px.Pxmc ?? "",
910 911 SalesQuantity = SqlFunc.AggregateSum(px.ProjectNumber),
911   - SalesAmount = SqlFunc.AggregateSum(px.ActualPrice > 0 ? px.ActualPrice : px.TotalPrice),
  912 + SalesAmountActual = SqlFunc.AggregateSum(px.ActualPrice),
  913 + SalesAmountTotal = SqlFunc.AggregateSum(px.TotalPrice),
912 914 SalesCount = SqlFunc.AggregateCount(px.Id)
913 915 })
914 916 .ToListAsync();
915 917  
  918 + // 计算实际销售金额(ActualPrice > 0 时使用 ActualPrice,否则使用 TotalPrice)
  919 + var itemStatisticsWithAmount = itemStatistics.Select(stat => new
  920 + {
  921 + stat.ItemId,
  922 + stat.ItemName,
  923 + stat.SalesQuantity,
  924 + SalesAmount = stat.SalesAmountActual > 0 ? stat.SalesAmountActual : stat.SalesAmountTotal,
  925 + stat.SalesCount
  926 + }).ToList();
  927 +
916 928 // 6. 单独统计每个品项的开单数量(去重开单ID)
917 929 var itemList = new List<ItemStatisticsItem>();
918   - foreach (var stat in itemStatistics)
  930 + foreach (var stat in itemStatisticsWithAmount)
919 931 {
920 932 var billingCountQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>(
921 933 (px, kd) => px.Glkdbh == kd.Id)
... ... @@ -981,6 +993,20 @@ namespace NCC.Extend.LqPackageInfo
981 993 /// "storeIds": ["门店ID1", "门店ID2"]
982 994 /// }
983 995 /// ```
  996 + ///
  997 + /// 返回格式(层级结构):
  998 + /// - ActivityId: 营销活动ID
  999 + /// - ActivityName: 营销活动名称
  1000 + /// - StoreList: 门店统计列表
  1001 + /// - StoreId: 门店ID
  1002 + /// - StoreName: 门店名称
  1003 + /// - ItemList: 该门店下的品项统计列表
  1004 + /// - ItemId: 品项ID
  1005 + /// - ItemName: 品项名称
  1006 + /// - SalesQuantity: 销售数量(项目次数总和)
  1007 + /// - SalesAmount: 销售金额
  1008 + /// - BillingCount: 开单数量(包含该品项的开单数)
  1009 + /// - SalesCount: 销售次数(品项明细记录数)
984 1010 /// </remarks>
985 1011 /// <param name="input">查询参数</param>
986 1012 /// <returns>按门店品项统计数据</returns>
... ... @@ -1021,6 +1047,7 @@ namespace NCC.Extend.LqPackageInfo
1021 1047 }
1022 1048  
1023 1049 // 5. 按门店和品项分组统计(先获取基础统计数据)
  1050 + // 注意:SqlSugar 的 AggregateSum 可能不支持三元运算符,需要先查询数据再计算
1024 1051 var storeItemStatistics = await baseQuery
1025 1052 .GroupBy((px, kd, md) => new
1026 1053 {
... ... @@ -1036,14 +1063,28 @@ namespace NCC.Extend.LqPackageInfo
1036 1063 ItemId = px.Px ?? "",
1037 1064 ItemName = px.Pxmc ?? "",
1038 1065 SalesQuantity = SqlFunc.AggregateSum(px.ProjectNumber),
1039   - SalesAmount = SqlFunc.AggregateSum(px.ActualPrice > 0 ? px.ActualPrice : px.TotalPrice),
  1066 + SalesAmountActual = SqlFunc.AggregateSum(px.ActualPrice),
  1067 + SalesAmountTotal = SqlFunc.AggregateSum(px.TotalPrice),
1040 1068 SalesCount = SqlFunc.AggregateCount(px.Id)
1041 1069 })
1042 1070 .ToListAsync();
1043 1071  
1044   - // 6. 单独统计每个门店品项的开单数量(去重开单ID)
1045   - var storeItemList = new List<StoreItemStatisticsItem>();
1046   - foreach (var stat in storeItemStatistics)
  1072 + // 计算实际销售金额(ActualPrice > 0 时使用 ActualPrice,否则使用 TotalPrice)
  1073 + var storeItemStatisticsWithAmount = storeItemStatistics.Select(stat => new
  1074 + {
  1075 + stat.StoreId,
  1076 + stat.StoreName,
  1077 + stat.ItemId,
  1078 + stat.ItemName,
  1079 + stat.SalesQuantity,
  1080 + SalesAmount = stat.SalesAmountActual > 0 ? stat.SalesAmountActual : stat.SalesAmountTotal,
  1081 + stat.SalesCount
  1082 + }).ToList();
  1083 +
  1084 + // 6. 单独统计每个门店品项的开单数量(去重开单ID),并组装成层级结构
  1085 + var storeItemDict = new Dictionary<string, List<StoreItemStatisticsItem>>();
  1086 +
  1087 + foreach (var stat in storeItemStatisticsWithAmount)
1047 1088 {
1048 1089 var billingCountQuery = _db.Queryable<LqKdPxmxEntity, LqKdKdjlbEntity>(
1049 1090 (px, kd) => px.Glkdbh == kd.Id)
... ... @@ -1064,28 +1105,53 @@ namespace NCC.Extend.LqPackageInfo
1064 1105 .Select((px, kd) => px.Glkdbh)
1065 1106 .CountAsync();
1066 1107  
1067   - storeItemList.Add(new StoreItemStatisticsItem
  1108 + var itemStat = new StoreItemStatisticsItem
1068 1109 {
1069   - StoreId = stat.StoreId ?? "",
1070   - StoreName = stat.StoreName ?? "",
1071 1110 ItemId = stat.ItemId ?? "",
1072 1111 ItemName = stat.ItemName ?? "",
1073 1112 SalesQuantity = stat.SalesQuantity,
1074 1113 SalesAmount = stat.SalesAmount,
1075 1114 BillingCount = billingCount,
1076 1115 SalesCount = stat.SalesCount
1077   - });
  1116 + };
  1117 +
  1118 + // 按门店分组
  1119 + var storeKey = stat.StoreId ?? "";
  1120 + if (!storeItemDict.ContainsKey(storeKey))
  1121 + {
  1122 + storeItemDict[storeKey] = new List<StoreItemStatisticsItem>();
  1123 + }
  1124 + storeItemDict[storeKey].Add(itemStat);
1078 1125 }
1079 1126  
1080   - // 7. 排序
1081   - storeItemList = storeItemList.OrderBy(x => x.StoreName).ThenBy(x => x.ItemName).ToList();
  1127 + // 7. 组装层级结构:门店 -> 品项列表
  1128 + var storeList = new List<StoreStatisticsWithItems>();
  1129 + foreach (var kvp in storeItemDict)
  1130 + {
  1131 + var firstItem = storeItemStatistics.FirstOrDefault(s => s.StoreId == kvp.Key);
  1132 + if (firstItem != null)
  1133 + {
  1134 + // 对品项列表排序
  1135 + var sortedItemList = kvp.Value.OrderBy(x => x.ItemName).ToList();
1082 1136  
1083   - // 7. 返回统计结果
  1137 + storeList.Add(new StoreStatisticsWithItems
  1138 + {
  1139 + StoreId = firstItem.StoreId ?? "",
  1140 + StoreName = firstItem.StoreName ?? "",
  1141 + ItemList = sortedItemList
  1142 + });
  1143 + }
  1144 + }
  1145 +
  1146 + // 8. 按门店名称排序
  1147 + storeList = storeList.OrderBy(x => x.StoreName).ToList();
  1148 +
  1149 + // 9. 返回统计结果
1084 1150 return new ActivityStatisticsByStoreItemOutput
1085 1151 {
1086 1152 ActivityId = input.ActivityId,
1087 1153 ActivityName = activity.ActivityName,
1088   - StoreItemList = storeItemList
  1154 + StoreList = storeList
1089 1155 };
1090 1156 }
1091 1157 catch (Exception ex)
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
... ... @@ -1073,45 +1073,62 @@ namespace NCC.Extend.LqStatistics
1073 1073 var startDate = new DateTime(now.Year, now.Month, 1);
1074 1074 var endDate = startDate.AddMonths(1).AddDays(-1);
1075 1075  
1076   - // 构建查询参数
1077   - var parameters = new Dictionary<string, object> { { "@startDate", startDate.ToString("yyyy-MM-dd 00:00:00") }, { "@endDate", endDate.ToString("yyyy-MM-dd 23:59:59") } };
  1076 + // 获取当前月份(YYYYMM格式)
  1077 + var currentMonth = now.ToString("yyyyMM");
1078 1078  
1079   - // 查询本月全门店统计数据
1080   - var sql =
1081   - @"
  1079 + // 1. 获取本月的门店目标业绩总和(从门店目标表获取 F_StoreTarget 字段,按月份过滤)
  1080 + var targetPerformanceSql = @"
1082 1081 SELECT
1083   - SUM(target_performance) AS TotalTargetPerformance,
1084   - SUM(actual_performance) AS TotalActualPerformance,
1085   - CASE
1086   - WHEN SUM(target_performance) > 0
1087   - THEN (SUM(actual_performance) / SUM(target_performance)) * 100
1088   - ELSE 0
1089   - END AS TotalCompletionRate
1090   - FROM v_store_performance_simple";
  1082 + COALESCE(SUM(F_StoreTarget), 0) AS TotalTargetPerformance
  1083 + FROM lq_md_target
  1084 + WHERE F_Month = @month";
1091 1085  
1092   - var result = await _db.Ado.SqlQueryAsync<dynamic>(sql, parameters);
1093   - var stats = result.FirstOrDefault();
  1086 + var targetParameters = new Dictionary<string, object>
  1087 + {
  1088 + { "@month", currentMonth }
  1089 + };
1094 1090  
1095   - if (stats != null)
  1091 + var targetResult = await _db.Ado.SqlQueryAsync<dynamic>(targetPerformanceSql, targetParameters);
  1092 + var targetPerformance = 0m;
  1093 + if (targetResult != null && targetResult.Any())
1096 1094 {
1097   - var targetPerformance = Convert.ToDecimal(stats.TotalTargetPerformance ?? 0);
1098   - var actualPerformance = Convert.ToDecimal(stats.TotalActualPerformance ?? 0);
1099   - var completionRate = Convert.ToDecimal(stats.TotalCompletionRate ?? 0);
  1095 + targetPerformance = Convert.ToDecimal(targetResult.FirstOrDefault()?.TotalTargetPerformance ?? 0);
  1096 + }
1100 1097  
1101   - return new
1102   - {
1103   - TargetPerformance = targetPerformance,
1104   - ActualPerformance = actualPerformance,
1105   - CompletionRate = completionRate,
1106   - Month = now.ToString("yyyy年MM月"),
1107   - };
  1098 + // 2. 从开单记录表获取本月实付金额的总和(sfyj 字段)
  1099 + var actualPerformanceSql = @"
  1100 + SELECT
  1101 + COALESCE(SUM(sfyj), 0) AS TotalActualPerformance
  1102 + FROM lq_kd_kdjlb
  1103 + WHERE F_IsEffective = 1
  1104 + AND kdrq >= @startDate
  1105 + AND kdrq <= @endDate";
  1106 +
  1107 + var parameters = new Dictionary<string, object>
  1108 + {
  1109 + { "@startDate", startDate.ToString("yyyy-MM-dd 00:00:00") },
  1110 + { "@endDate", endDate.ToString("yyyy-MM-dd 23:59:59") }
  1111 + };
  1112 +
  1113 + var actualResult = await _db.Ado.SqlQueryAsync<dynamic>(actualPerformanceSql, parameters);
  1114 + var actualPerformance = 0m;
  1115 + if (actualResult != null && actualResult.Any())
  1116 + {
  1117 + actualPerformance = Convert.ToDecimal(actualResult.FirstOrDefault()?.TotalActualPerformance ?? 0);
  1118 + }
  1119 +
  1120 + // 3. 计算完成率
  1121 + var completionRate = 0m;
  1122 + if (targetPerformance > 0)
  1123 + {
  1124 + completionRate = (actualPerformance / targetPerformance) * 100m;
1108 1125 }
1109 1126  
1110 1127 return new
1111 1128 {
1112   - TargetPerformance = 0m,
1113   - ActualPerformance = 0m,
1114   - CompletionRate = 0m,
  1129 + TargetPerformance = targetPerformance,
  1130 + ActualPerformance = actualPerformance,
  1131 + CompletionRate = decimal.Round(completionRate, 2),
1115 1132 Month = now.ToString("yyyy年MM月"),
1116 1133 };
1117 1134 }
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqXhHyhkService.cs
... ... @@ -964,6 +964,13 @@ namespace NCC.Extend.LqXhHyhk
964 964 {
965 965 // 开启事务
966 966 _db.BeginTran();
  967 + // 查询会员信息
  968 + var memberInfo = await _db.Queryable<LqKhxxEntity>().Where(w => w.Id == entity.Hy).FirstAsync();
  969 + //如果会员类型是线索,那么就更新为新客
  970 + if (memberInfo.Khlx == MemberTypeEnum.线索.GetHashCode().ToString())
  971 + {
  972 + memberInfo.Khlx = MemberTypeEnum.新客.GetHashCode().ToString();
  973 + }
967 974 // 新增会员耗卡记录
968 975 var newEntity = await _db.Insertable(entity).IgnoreColumns(ignoreNullColumn: true).ExecuteReturnEntityAsync();
969 976 // 收集所有需要插入的实体,然后批量插入
... ...