Commit a30ca3d5eaa888da35dd992a47269cfabaa1361c

Authored by “wangming”
1 parent a78c0ae8

feat: 添加事业部开单统计功能;修复科技部老师统计方法,不使用视图直接从表查询;优化错误处理返回全0结果

netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/BusinessUnitBillingStatisticsInput.cs 0 → 100644
  1 +using System;
  2 +
  3 +namespace NCC.Extend.Entitys.Dto.LqDailyReport
  4 +{
  5 + /// <summary>
  6 + /// 事业部开单统计查询输入
  7 + /// </summary>
  8 + public class BusinessUnitBillingStatisticsInput
  9 + {
  10 + /// <summary>
  11 + /// 统计日期(格式:yyyy-MM-dd)
  12 + /// </summary>
  13 + public string Date { get; set; }
  14 + }
  15 +}
  16 +
... ...
netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqDailyReport/BusinessUnitBillingStatisticsOutput.cs 0 → 100644
  1 +using System;
  2 +using System.Collections.Generic;
  3 +
  4 +namespace NCC.Extend.Entitys.Dto.LqDailyReport
  5 +{
  6 + /// <summary>
  7 + /// 事业部开单统计输出
  8 + /// </summary>
  9 + public class BusinessUnitBillingStatisticsOutput
  10 + {
  11 + /// <summary>
  12 + /// 事业部ID
  13 + /// </summary>
  14 + public string BusinessUnitId { get; set; }
  15 +
  16 + /// <summary>
  17 + /// 事业部名称
  18 + /// </summary>
  19 + public string BusinessUnitName { get; set; }
  20 +
  21 + /// <summary>
  22 + /// 总业绩
  23 + /// </summary>
  24 + public decimal TotalPerformance { get; set; }
  25 +
  26 + /// <summary>
  27 + /// 总单量
  28 + /// </summary>
  29 + public int TotalOrderCount { get; set; }
  30 +
  31 + /// <summary>
  32 + /// 开单列表
  33 + /// </summary>
  34 + public List<BillingOrderInfo> Orders { get; set; }
  35 + }
  36 +
  37 + /// <summary>
  38 + /// 开单信息
  39 + /// </summary>
  40 + public class BillingOrderInfo
  41 + {
  42 + /// <summary>
  43 + /// 开单ID
  44 + /// </summary>
  45 + public string OrderId { get; set; }
  46 +
  47 + /// <summary>
  48 + /// 门店名称
  49 + /// </summary>
  50 + public string StoreName { get; set; }
  51 +
  52 + /// <summary>
  53 + /// 健康师姓名(多个用逗号分隔)
  54 + /// </summary>
  55 + public string HealthTeacherNames { get; set; }
  56 +
  57 + /// <summary>
  58 + /// 金额
  59 + /// </summary>
  60 + public decimal Amount { get; set; }
  61 +
  62 + /// <summary>
  63 + /// 开单时间
  64 + /// </summary>
  65 + public DateTime? OrderTime { get; set; }
  66 + }
  67 +}
  68 +
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
... ... @@ -12,6 +12,7 @@ using SqlSugar;
12 12 using System;
13 13 using System.Collections.Generic;
14 14 using System.Linq;
  15 +using System.Text;
15 16 using System.Threading.Tasks;
16 17 using Yitter.IdGenerator;
17 18 using NCC.Common.Helper;
... ... @@ -22,6 +23,10 @@ using NCC.DataEncryption;
22 23 using NCC.ClayObject;
23 24 using NCC.Extend.Entitys.Dto.LqDailyReport;
24 25 using NCC.Extend.Entitys.lq_kd_kdjlb;
  26 +using NCC.Extend.Entitys.lq_kd_jksyj;
  27 +using NCC.Extend.Entitys.lq_mdxx;
  28 +using NCC.System.Entitys.Permission;
  29 +using NCC.Extend.Entitys.Enum;
25 30 using Microsoft.AspNetCore.Authorization;
26 31  
27 32 namespace NCC.Extend
... ... @@ -957,7 +962,198 @@ namespace NCC.Extend
957 962  
958 963 return outputList;
959 964 }
  965 +
  966 + /// <summary>
  967 + /// 获取指定日期的事业部开单统计数据
  968 + /// </summary>
  969 + /// <remarks>
  970 + /// 统计指定日期的事业部开单数据,包括:
  971 + /// - 只统计有效的开单(F_IsEffective = 1)
  972 + /// - 只统计有金额的开单(sfyj > 0)
  973 + /// - 只统计有效的健康师业绩(F_IsEffective = 1)
  974 + /// - 如果有多个健康师就合并显示
  975 + /// - 按照事业部名称排序
  976 + /// - 每个事业部内的开单按照时间先后顺序进行排序
  977 + ///
  978 + /// 示例请求:
  979 + /// ```json
  980 + /// {
  981 + /// "date": "2025-11-10"
  982 + /// }
  983 + /// ```
  984 + /// </remarks>
  985 + /// <param name="input">查询参数</param>
  986 + /// <returns>事业部开单统计数据列表</returns>
  987 + /// <response code="200">成功返回统计数据</response>
  988 + /// <response code="400">日期格式错误或参数无效</response>
  989 + /// <response code="500">服务器内部错误</response>
  990 + [HttpPost("get-business-unit-billing-statistics")]
  991 + [AllowAnonymous]
  992 + public async Task<List<BusinessUnitBillingStatisticsOutput>> GetBusinessUnitBillingStatistics(BusinessUnitBillingStatisticsInput input)
  993 + {
  994 + try
  995 + {
  996 + // 1. 验证日期参数
  997 + if (string.IsNullOrEmpty(input.Date))
  998 + {
  999 + throw NCCException.Oh("日期不能为空");
  1000 + }
  1001 +
  1002 + if (!DateTime.TryParse(input.Date, out var targetDate))
  1003 + {
  1004 + throw NCCException.Oh("日期格式错误,请使用 yyyy-MM-dd 格式");
  1005 + }
  1006 +
  1007 + // 2. 查询指定日期的有效开单记录(有金额的)
  1008 + var billingQuery = _db.Queryable<LqKdKdjlbEntity, LqMdxxEntity, OrganizeEntity>(
  1009 + (billing, store, org) => billing.Djmd == store.Id && store.Syb == org.Id)
  1010 + .Where((billing, store, org) => billing.IsEffective == StatusEnum.有效.GetHashCode())
  1011 + .Where((billing, store, org) => billing.Sfyj > 0) // 只统计有金额的开单
  1012 + .Where((billing, store, org) => billing.Kdrq.HasValue && billing.Kdrq.Value.Date == targetDate.Date)
  1013 + .Where((billing, store, org) => org.Category == "department")
  1014 + .Where((billing, store, org) => org.FullName.Contains("事业"))
  1015 + .Select((billing, store, org) => new
  1016 + {
  1017 + OrderId = billing.Id,
  1018 + StoreName = store.Dm,
  1019 + BusinessUnitId = org.Id,
  1020 + BusinessUnitName = org.FullName,
  1021 + Amount = billing.Sfyj,
  1022 + OrderTime = billing.Kdrq,
  1023 + })
  1024 + .ToListAsync();
  1025 +
  1026 + var billingRecords = await billingQuery;
  1027 +
  1028 + if (!billingRecords.Any())
  1029 + {
  1030 + return new List<BusinessUnitBillingStatisticsOutput>();
  1031 + }
  1032 +
  1033 + // 3. 批量查询健康师信息
  1034 + var orderIds = billingRecords.Select(x => x.OrderId).Distinct().ToList();
  1035 + var healthTeachers = await _db.Queryable<LqKdJksyjEntity>()
  1036 + .Where(x => orderIds.Contains(x.Glkdbh) && x.IsEffective == StatusEnum.有效.GetHashCode())
  1037 + .Select(x => new
  1038 + {
  1039 + OrderId = x.Glkdbh,
  1040 + TeacherName = x.Jksxm,
  1041 + })
  1042 + .ToListAsync();
  1043 +
  1044 + // 4. 按开单ID分组健康师
  1045 + var healthTeacherDict = healthTeachers
  1046 + .GroupBy(x => x.OrderId)
  1047 + .ToDictionary(
  1048 + g => g.Key,
  1049 + g => string.Join("、", g.Select(x => x.TeacherName).Distinct())
  1050 + );
  1051 +
  1052 + // 5. 按事业部分组统计
  1053 + var result = billingRecords
  1054 + .GroupBy(x => new { x.BusinessUnitId, x.BusinessUnitName })
  1055 + .Select(g => new BusinessUnitBillingStatisticsOutput
  1056 + {
  1057 + BusinessUnitId = g.Key.BusinessUnitId,
  1058 + BusinessUnitName = g.Key.BusinessUnitName,
  1059 + TotalPerformance = g.Sum(x => x.Amount),
  1060 + TotalOrderCount = g.Count(),
  1061 + Orders = g.OrderBy(x => x.OrderTime ?? DateTime.MinValue)
  1062 + .Select(x => new BillingOrderInfo
  1063 + {
  1064 + OrderId = x.OrderId,
  1065 + StoreName = x.StoreName,
  1066 + HealthTeacherNames = healthTeacherDict.GetValueOrDefault(x.OrderId, ""),
  1067 + Amount = x.Amount,
  1068 + OrderTime = x.OrderTime,
  1069 + })
  1070 + .ToList(),
  1071 + })
  1072 + .OrderBy(x => x.BusinessUnitName) // 按事业部名称排序
  1073 + .ToList();
  1074 +
  1075 + return result;
  1076 + }
  1077 + catch (Exception ex)
  1078 + {
  1079 + throw NCCException.Oh($"获取事业部开单统计数据失败: {ex.Message}", ex);
  1080 + }
  1081 + }
  1082 +
  1083 + /// <summary>
  1084 + /// 将事业部开单统计数据格式化为中文文本
  1085 + /// </summary>
  1086 + /// <remarks>
  1087 + /// 将结构化的统计数据格式化为中文文本格式,用于显示或发送消息。
  1088 + ///
  1089 + /// 示例请求:
  1090 + /// ```json
  1091 + /// {
  1092 + /// "date": "2025-11-10"
  1093 + /// }
  1094 + /// ```
  1095 + ///
  1096 + /// 返回格式:
  1097 + /// ```
  1098 + /// 事业一部业绩:xxxx
  1099 + /// 事业一部总单量:xxx
  1100 + /// 第一单:xxx店、xxx健康师,金额xxx
  1101 + /// 第二单:xxx店、xxx健康师,金额xxx
  1102 + ///
  1103 + /// 事业二部业绩:xxxx
  1104 + /// 事业二部总单量:xxx
  1105 + /// 第一单:xxx店、xxx健康师,金额xxx
  1106 + /// 第二单:xxx店、xxx健康师,金额xxx
  1107 + /// ```
  1108 + /// </remarks>
  1109 + /// <param name="input">查询参数</param>
  1110 + /// <returns>格式化的中文文本</returns>
  1111 + /// <response code="200">成功返回格式化文本</response>
  1112 + /// <response code="400">日期格式错误或参数无效</response>
  1113 + /// <response code="500">服务器内部错误</response>
  1114 + [HttpPost("get-business-unit-billing-statistics-text")]
  1115 + [AllowAnonymous]
  1116 + public async Task<string> GetBusinessUnitBillingStatisticsText(BusinessUnitBillingStatisticsInput input)
  1117 + {
  1118 + try
  1119 + {
  1120 + // 1. 获取统计数据
  1121 + var statistics = await GetBusinessUnitBillingStatistics(input);
  1122 +
  1123 + if (!statistics.Any())
  1124 + {
  1125 + return $"日期 {input.Date} 暂无开单数据";
  1126 + }
  1127 +
  1128 + // 2. 格式化为中文文本
  1129 + var textBuilder = new StringBuilder();
  1130 +
  1131 + foreach (var unit in statistics)
  1132 + {
  1133 + textBuilder.AppendLine($"{unit.BusinessUnitName}业绩:{unit.TotalPerformance:F2}");
  1134 + textBuilder.AppendLine($"{unit.BusinessUnitName}总单量:{unit.TotalOrderCount}");
  1135 +
  1136 + int orderIndex = 1;
  1137 + foreach (var order in unit.Orders)
  1138 + {
  1139 + var teacherNames = string.IsNullOrEmpty(order.HealthTeacherNames) ? "无健康师" : order.HealthTeacherNames;
  1140 + textBuilder.AppendLine($"第{orderIndex}单:{order.StoreName}、{teacherNames},金额{order.Amount:F2}");
  1141 + orderIndex++;
  1142 + }
  1143 +
  1144 + textBuilder.AppendLine(); // 空行分隔
  1145 + }
  1146 +
  1147 + return textBuilder.ToString().TrimEnd();
  1148 + }
  1149 + catch (Exception ex)
  1150 + {
  1151 + throw NCCException.Oh($"获取事业部开单统计文本失败: {ex.Message}", ex);
  1152 + }
  1153 + }
960 1154 #endregion
  1155 +
  1156 +
961 1157 }
962 1158 }
963 1159  
... ...
netcore/src/Modularity/Extend/NCC.Extend/LqStatisticsService.cs
... ... @@ -28,8 +28,11 @@ using NCC.Extend.Entitys.lq_kd_kjbsyj;
28 28 using NCC.Extend.Entitys.lq_mdxx;
29 29 using NCC.Extend.Entitys.lq_md_xdbhsj;
30 30 using NCC.Extend.Entitys.lq_xh_kjbsyj;
  31 +using NCC.Extend.Entitys.lq_xh_hyhk;
  32 +using NCC.Extend.Entitys.lq_xh_pxmx;
31 33 using NCC.Extend.Entitys.lq_ycsd_jsj;
32 34 using NCC.Extend.Entitys.lq_yjmxb;
  35 +using NCC.Extend.Entitys.Enum;
33 36 using NCC.Extend.Entitys.lq_statistics_gold_triangle;
34 37 using NCC.Extend.Entitys.lq_statistics_personal_performance;
35 38 using NCC.Extend.Entitys.lq_statistics_store_consume_performance;
... ... @@ -870,125 +873,144 @@ namespace NCC.Extend.LqStatistics
870 873 public async Task<List<TechTeacherSimpleStatisticsOutput>> GetTechTeacherStatistics(TechTeacherStatisticsInput input)
871 874 {
872 875 try
873   - { // 1. 从用户表获取所有科技部老师
874   - var allTeachers = await _db.Queryable<UserEntity>()
875   - .Where(x => x.Gw == "科技老师")
  876 + {
  877 + // 1. 验证必须传入科技老师ID
  878 + if (string.IsNullOrEmpty(input.TeacherId))
  879 + {
  880 + return new List<TechTeacherSimpleStatisticsOutput>
  881 + {
  882 + new TechTeacherSimpleStatisticsOutput
  883 + {
  884 + DepartmentName = "科技部",
  885 + TeacherName = "",
  886 + OrderAchievement = 0m,
  887 + OrderItemCount = 0,
  888 + ConsumeAchievement = 0m,
  889 + ConsumeItemCount = 0,
  890 + ConsumeProjectCount = 0,
  891 + ConsumeLaborCost = 0m,
  892 + }
  893 + };
  894 + }
  895 +
  896 + // 2. 获取科技老师信息
  897 + var teacher = await _db.Queryable<UserEntity>()
  898 + .Where(x => x.Gw == "科技老师" && x.Id == input.TeacherId)
876 899 .Select(x => new
877 900 {
878 901 TeacherId = x.Id,
879 902 TeacherName = x.RealName,
880 903 TeacherAccount = x.Account,
881 904 })
882   - .ToListAsync();
883   -
884   - // 2. 获取业绩流水数据
885   - var flowQuery = _db.Queryable<VTechTeacherFlowEntity>();
  905 + .FirstAsync();
886 906  
887   - // 老师过滤(支持通过ID或账号匹配)
888   - if (!string.IsNullOrEmpty(input.TeacherId))
  907 + if (teacher == null)
889 908 {
890   - // 先通过用户ID查询账号,然后同时匹配ID和账号
891   - var teacherAccount = allTeachers.FirstOrDefault(t => t.TeacherId == input.TeacherId)?.TeacherAccount;
892   - if (!string.IsNullOrEmpty(teacherAccount))
  909 + return new List<TechTeacherSimpleStatisticsOutput>
893 910 {
894   - // 同时匹配ID和账号(因为视图中的teacher_id可能是ID或账号)
895   - flowQuery = flowQuery.Where(x => x.TeacherId == input.TeacherId || x.TeacherAccount == teacherAccount);
896   - }
897   - else
898   - {
899   - // 如果找不到账号,只匹配ID
900   - flowQuery = flowQuery.Where(x => x.TeacherId == input.TeacherId);
901   - }
  911 + new TechTeacherSimpleStatisticsOutput
  912 + {
  913 + DepartmentName = "科技部",
  914 + TeacherName = "",
  915 + OrderAchievement = 0m,
  916 + OrderItemCount = 0,
  917 + ConsumeAchievement = 0m,
  918 + ConsumeItemCount = 0,
  919 + ConsumeProjectCount = 0,
  920 + ConsumeLaborCost = 0m,
  921 + }
  922 + };
902 923 }
903 924  
904   - if (!string.IsNullOrEmpty(input.TeacherName))
905   - {
906   - flowQuery = flowQuery.Where(x => x.TeacherName.Contains(input.TeacherName));
907   - }
  925 + // 3. 查询开单业绩(从 lq_kd_kjbsyj 关联 lq_kd_kdjlb 和 lq_kd_pxmx)
  926 + var orderQuery = _db.Queryable<LqKdKjbsyjEntity, LqKdKdjlbEntity, LqKdPxmxEntity>(
  927 + (kjbsyj, kdjlb, pxmx) => kjbsyj.Glkdbh == kdjlb.Id && kjbsyj.Kdpxid == pxmx.Id)
  928 + .Where((kjbsyj, kdjlb, pxmx) => kjbsyj.IsEffective == StatusEnum.有效.GetHashCode())
  929 + .Where((kjbsyj, kdjlb, pxmx) => kdjlb.IsEffective == StatusEnum.有效.GetHashCode())
  930 + .Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Kjblszh == teacher.TeacherAccount);
908 931  
909 932 // 日期过滤
910 933 if (input.StartDate.HasValue)
911 934 {
912   - flowQuery = flowQuery.Where(x => x.BusinessDate >= input.StartDate.Value);
  935 + orderQuery = orderQuery.Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Yjsj >= input.StartDate.Value);
913 936 }
914 937  
915 938 if (input.EndDate.HasValue)
916 939 {
917   - flowQuery = flowQuery.Where(x => x.BusinessDate <= input.EndDate.Value);
  940 + orderQuery = orderQuery.Where((kjbsyj, kdjlb, pxmx) => kjbsyj.Yjsj <= input.EndDate.Value);
918 941 }
919 942  
920   - var flowRecords = await flowQuery.ToListAsync();
921   -
922   - // 3. 按老师账号分组统计业绩数据(包括耗卡手工费)
923   - // 注意:视图中的teacher_id是kjbls,teacher_account是kjblszh,使用账号来匹配更准确
924   - var teacherStatsDict = flowRecords
925   - .GroupBy(x => new
  943 + var orderStats = await orderQuery
  944 + .Select((kjbsyj, kdjlb, pxmx) => new
926 945 {
927   - TeacherAccount = x.TeacherAccount ?? string.Empty,
928   - TeacherId = x.TeacherId ?? string.Empty,
929   - TeacherName = x.TeacherName ?? string.Empty,
  946 + OrderAchievement = SqlFunc.ToDecimal(kjbsyj.Kjblsyj),
  947 + OrderItemCount = SqlFunc.ToInt32(pxmx.ProjectNumber),
930 948 })
931   - .ToDictionary(
932   - g => g.Key.TeacherAccount ?? string.Empty,
933   - g => new
934   - {
935   - ConsumeProjectCount = (int)(g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ProjectCount)),
936   - ConsumeAchievement = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.Achievement),
937   - OrderAchievement = g.Where(x => x.BusinessType == "开卡").Sum(x => x.Achievement),
938   - OrderItemCount = g.Where(x => x.BusinessType == "开卡").Sum(x => x.ItemCount),
939   - ConsumeItemCount = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.ItemCount),
940   - ConsumeLaborCost = g.Where(x => x.BusinessType == "耗卡").Sum(x => x.LaborCost),
941   - }
942   - );
  949 + .ToListAsync();
943 950  
944   - // 4. 构建结果,包含所有老师
945   - var result = new List<TechTeacherSimpleStatisticsOutput>();
  951 + // 4. 查询耗卡业绩(从 lq_xh_kjbsyj 关联 lq_xh_hyhk 和 lq_xh_pxmx)
  952 + // 注意:lq_xh_kjbsyj.kjbls 字段存储的是健康师id,不是科技部老师id
  953 + // 科技部老师信息在 kjblszh(账号)和 kjblsxm(姓名)字段
  954 + var consumeQuery = _db.Queryable<LqXhKjbsyjEntity, LqXhHyhkEntity, LqXhPxmxEntity>(
  955 + (kjbsyj, hyhk, pxmx) => kjbsyj.Glkdbh == hyhk.Id && kjbsyj.Hkpxid == pxmx.Id)
  956 + .Where((kjbsyj, hyhk, pxmx) => kjbsyj.IsEffective == StatusEnum.有效.GetHashCode())
  957 + .Where((kjbsyj, hyhk, pxmx) => hyhk.IsEffective == StatusEnum.有效.GetHashCode())
  958 + .Where((kjbsyj, hyhk, pxmx) => kjbsyj.Kjblszh == teacher.TeacherAccount);
946 959  
947   - foreach (var teacher in allTeachers)
  960 + // 日期过滤
  961 + if (input.StartDate.HasValue)
948 962 {
949   - // 应用过滤条件
950   - if (!string.IsNullOrEmpty(input.TeacherId) && teacher.TeacherId != input.TeacherId)
951   - continue;
952   -
953   - if (!string.IsNullOrEmpty(input.TeacherName) && !teacher.TeacherName.Contains(input.TeacherName))
954   - continue;
  963 + consumeQuery = consumeQuery.Where((kjbsyj, hyhk, pxmx) => kjbsyj.Yjsj >= input.StartDate.Value);
  964 + }
955 965  
956   - // 使用账号来匹配业绩数据(因为视图中的teacher_account是kjblszh)
957   - var teacherAccount = teacher.TeacherAccount ?? string.Empty;
958   - var stats = teacherStatsDict.GetValueOrDefault(
959   - teacherAccount,
960   - new
961   - {
962   - ConsumeProjectCount = 0,
963   - ConsumeAchievement = 0m,
964   - OrderAchievement = 0m,
965   - OrderItemCount = 0,
966   - ConsumeItemCount = 0,
967   - ConsumeLaborCost = 0m,
968   - }
969   - );
  966 + if (input.EndDate.HasValue)
  967 + {
  968 + consumeQuery = consumeQuery.Where((kjbsyj, hyhk, pxmx) => kjbsyj.Yjsj <= input.EndDate.Value);
  969 + }
970 970  
971   - var teacherStats = new TechTeacherSimpleStatisticsOutput
  971 + var consumeStats = await consumeQuery
  972 + .Select((kjbsyj, hyhk, pxmx) => new
972 973 {
973   - DepartmentName = "科技部", // 固定为科技部
974   - TeacherName = teacher.TeacherName,
975   - ConsumeProjectCount = stats.ConsumeProjectCount,
976   - ConsumeAchievement = stats.ConsumeAchievement,
977   - OrderAchievement = stats.OrderAchievement,
978   - OrderItemCount = stats.OrderItemCount,
979   - ConsumeItemCount = stats.ConsumeItemCount,
980   - ConsumeLaborCost = stats.ConsumeLaborCost,
981   - };
  974 + ConsumeAchievement = kjbsyj.Kjblsyj,
  975 + ConsumeItemCount = SqlFunc.ToInt32(pxmx.ProjectNumber),
  976 + ConsumeProjectCount = SqlFunc.ToInt32(kjbsyj.HdpxNumber),
  977 + ConsumeLaborCost = kjbsyj.LaborCost,
  978 + })
  979 + .ToListAsync();
982 980  
983   - result.Add(teacherStats);
984   - }
  981 + // 5. 统计并返回结果
  982 + var result = new TechTeacherSimpleStatisticsOutput
  983 + {
  984 + DepartmentName = "科技部",
  985 + TeacherName = teacher.TeacherName,
  986 + OrderAchievement = orderStats.Sum(x => x.OrderAchievement != null && decimal.TryParse(x.OrderAchievement.ToString(), out var val) ? val : 0m),
  987 + OrderItemCount = orderStats.Sum(x => x.OrderItemCount),
  988 + ConsumeAchievement = consumeStats.Sum(x => x.ConsumeAchievement ?? 0m),
  989 + ConsumeItemCount = consumeStats.Sum(x => x.ConsumeItemCount),
  990 + ConsumeProjectCount = consumeStats.Sum(x => x.ConsumeProjectCount),
  991 + ConsumeLaborCost = consumeStats.Sum(x => x.ConsumeLaborCost ?? 0m),
  992 + };
985 993  
986   - return result;
  994 + return new List<TechTeacherSimpleStatisticsOutput> { result };
987 995 }
988 996 catch (Exception ex)
989 997 {
990 998 _logger.LogError(ex, "获取科技部老师业绩统计时发生错误");
991   - throw NCCException.Oh("获取科技部老师业绩统计失败", ex);
  999 + // 发生错误时返回全0的结果,而不是抛出异常
  1000 + return new List<TechTeacherSimpleStatisticsOutput>
  1001 + {
  1002 + new TechTeacherSimpleStatisticsOutput
  1003 + {
  1004 + DepartmentName = "科技部",
  1005 + TeacherName = "",
  1006 + OrderAchievement = 0m,
  1007 + OrderItemCount = 0,
  1008 + ConsumeAchievement = 0m,
  1009 + ConsumeItemCount = 0,
  1010 + ConsumeProjectCount = 0,
  1011 + ConsumeLaborCost = 0m,
  1012 + }
  1013 + };
992 1014 }
993 1015 }
994 1016  
... ...