|
|
@@ -0,0 +1,255 @@
|
|
|
+using EasyTemplate.Tool;
|
|
|
+using EasyTemplate.Tool.Entity;
|
|
|
+using EasyTemplate.Tool.Entity.App;
|
|
|
+using SqlSugar;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace EasyTemplate.Service
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 预警告统计服务
|
|
|
+ /// </summary>
|
|
|
+ public class WarningService
|
|
|
+ {
|
|
|
+ private readonly SqlSugarRepository<TPrewarning> _prewarning;
|
|
|
+ private readonly SqlSugarRepository<TRecord> _record;
|
|
|
+
|
|
|
+ public WarningService(SqlSugarRepository<TPrewarning> prewarning, SqlSugarRepository<TRecord> record)
|
|
|
+ {
|
|
|
+ _prewarning = prewarning;
|
|
|
+ _record = record;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取 35 天内所有油枪的统计数据
|
|
|
+ /// </summary>
|
|
|
+ public async Task<List<WarningStatistics>> Get35DaysStatisticsAsync()
|
|
|
+ {
|
|
|
+ var endDate = DateOnly.FromDateTime(DateTime.Today);
|
|
|
+ var startDate = endDate.AddDays(-34); // 包含今天共 35 天
|
|
|
+
|
|
|
+ return await CalculateStatisticsAsync(startDate, endDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 按日期范围获取统计数据
|
|
|
+ /// </summary>
|
|
|
+ public async Task<List<WarningStatistics>> GetStatisticsByDateRangeAsync(DateOnly startDate, DateOnly endDate)
|
|
|
+ {
|
|
|
+ return await CalculateStatisticsAsync(startDate, endDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 按油枪和日期范围筛选统计数据
|
|
|
+ /// </summary>
|
|
|
+ public async Task<List<WarningStatistics>> GetStatisticsByFilterAsync(WarningStatisticsQuery query)
|
|
|
+ {
|
|
|
+ var endDate = query.EndDate ?? DateOnly.FromDateTime(DateTime.Today);
|
|
|
+ var startDate = query.StartDate ?? endDate.AddDays(-34);
|
|
|
+
|
|
|
+ var allStats = await CalculateStatisticsAsync(startDate, endDate);
|
|
|
+
|
|
|
+ // 按油枪筛选
|
|
|
+ if (query.NozzleId.HasValue)
|
|
|
+ {
|
|
|
+ allStats = allStats.Where(s => s.nozzle == query.NozzleId.Value).ToList();
|
|
|
+ }
|
|
|
+
|
|
|
+ return allStats;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 更新指定日期的统计数据(用于新交易插入后)
|
|
|
+ /// </summary>
|
|
|
+ public async Task UpdateDailyStatisticsAsync(DateOnly date, int nozzleId)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ Console.WriteLine($"[预警告统计] 开始更新油枪{nozzleId},日期:{date} 的统计数据");
|
|
|
+
|
|
|
+ // 重新计算该油枪在该日期的统计
|
|
|
+ var stats = await CalculateSingleDayStatisticsAsync(date, nozzleId);
|
|
|
+
|
|
|
+ if (stats != null)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"[预警告统计] 更新成功 - 总笔数:{stats.daily_total}, 超标:{stats.daily_overproof}, 超标率:{stats.daily_overproofrate}%");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"[预警告统计] 更新失败:{ex.Message}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算单个日期的统计数据
|
|
|
+ /// </summary>
|
|
|
+ private async Task<WarningStatistics> CalculateSingleDayStatisticsAsync(DateOnly date, int nozzleId)
|
|
|
+ {
|
|
|
+ // 获取当天的预警告记录
|
|
|
+ var prewarning = await _prewarning.AsQueryable()
|
|
|
+ .Where(p => p.date == date && p.nozzle == nozzleId)
|
|
|
+ .FirstAsync();
|
|
|
+
|
|
|
+ if (prewarning == null)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return new WarningStatistics
|
|
|
+ {
|
|
|
+ nozzle = nozzleId,
|
|
|
+ statistics_date = date,
|
|
|
+ daily_total = prewarning.total,
|
|
|
+ daily_overproof = prewarning.overproof,
|
|
|
+ daily_overproofrate = prewarning.overproofrate,
|
|
|
+ daily_overproof_alert = prewarning.overproof_alert,
|
|
|
+ daily_overproofrate_alert = prewarning.overproofrate_alert,
|
|
|
+ daily_overproof_2 = prewarning.overproof_2,
|
|
|
+ daily_overproofrate_2 = prewarning.overproofrate_2,
|
|
|
+ is_accumulated = prewarning.total >= 5,
|
|
|
+ accumulated_days = 1
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 核心统计计算逻辑
|
|
|
+ /// </summary>
|
|
|
+ private async Task<List<WarningStatistics>> CalculateStatisticsAsync(DateOnly startDate, DateOnly endDate)
|
|
|
+ {
|
|
|
+ Console.WriteLine($"[预警告统计] 开始计算统计,范围:{startDate} 至 {endDate}");
|
|
|
+
|
|
|
+ var results = new List<WarningStatistics>();
|
|
|
+
|
|
|
+ // 获取该日期范围内的所有预警告记录
|
|
|
+ var prewarnings = await _prewarning.AsQueryable()
|
|
|
+ .Where(p => p.date >= startDate && p.date <= endDate)
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ // 按油枪分组
|
|
|
+ var groupedByNozzle = prewarnings.GroupBy(p => p.nozzle);
|
|
|
+
|
|
|
+ foreach (var nozzleGroup in groupedByNozzle)
|
|
|
+ {
|
|
|
+ var nozzleId = nozzleGroup.Key;
|
|
|
+ var sortedData = nozzleGroup.OrderBy(p => p.date).ToList();
|
|
|
+
|
|
|
+ // 为每一天计算统计数据
|
|
|
+ for (int i = 0; i < sortedData.Count; i++)
|
|
|
+ {
|
|
|
+ var currentPrewarning = sortedData[i];
|
|
|
+ var currentDate = currentPrewarning.date;
|
|
|
+
|
|
|
+ var stats = new WarningStatistics
|
|
|
+ {
|
|
|
+ nozzle = nozzleId,
|
|
|
+ statistics_date = currentDate,
|
|
|
+ daily_total = currentPrewarning.total,
|
|
|
+ daily_overproof = currentPrewarning.overproof,
|
|
|
+ daily_overproofrate = currentPrewarning.overproofrate,
|
|
|
+ daily_overproof_alert = currentPrewarning.overproof_alert,
|
|
|
+ daily_overproofrate_alert = currentPrewarning.overproofrate_alert,
|
|
|
+ daily_overproof_2 = currentPrewarning.overproof_2,
|
|
|
+ daily_overproofrate_2 = currentPrewarning.overproofrate_2
|
|
|
+ };
|
|
|
+
|
|
|
+ // 计算 35 天累计统计
|
|
|
+ CalculateAccumulatedStatistics(sortedData, i, stats);
|
|
|
+
|
|
|
+ results.Add(stats);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Console.WriteLine($"[预警告统计] 计算完成,共{results.Count}条记录");
|
|
|
+ return results;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算累计统计数据(核心业务逻辑)
|
|
|
+ /// 规则:从当前日期往前找,直到累计笔数>=5 或达到 35 天上限
|
|
|
+ /// </summary>
|
|
|
+ private void CalculateAccumulatedStatistics(List<TPrewarning> sortedData, int currentIndex, WarningStatistics stats)
|
|
|
+ {
|
|
|
+ int accumulatedTotal = 0;
|
|
|
+ int accumulatedOverproof = 0;
|
|
|
+ int accumulatedOverproofAlert = 0;
|
|
|
+ int accumulatedOverproof2 = 0;
|
|
|
+ int accumulatedDays = 0;
|
|
|
+
|
|
|
+ // 从当前日期往前累加,直到满足条件或达到 35 天
|
|
|
+ for (int i = currentIndex; i >= 0 && (currentIndex - i) < 35; i--)
|
|
|
+ {
|
|
|
+ var day = sortedData[i];
|
|
|
+ accumulatedTotal += day.total;
|
|
|
+ accumulatedOverproof += day.overproof;
|
|
|
+ accumulatedOverproofAlert += day.overproof_alert;
|
|
|
+ accumulatedOverproof2 += day.overproof_2;
|
|
|
+ accumulatedDays++;
|
|
|
+
|
|
|
+ // 如果累计笔数>=5,停止累加
|
|
|
+ if (accumulatedTotal >= 5)
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置累计统计结果
|
|
|
+ stats.total_count = accumulatedTotal;
|
|
|
+ stats.total_overproof = accumulatedOverproof;
|
|
|
+ stats.total_overproof_alert = accumulatedOverproofAlert;
|
|
|
+ stats.total_overproof_2 = accumulatedOverproof2;
|
|
|
+ stats.accumulated_days = accumulatedDays;
|
|
|
+ stats.is_accumulated = accumulatedTotal >= 5;
|
|
|
+
|
|
|
+ // 计算累计超标率(避免除以 0)
|
|
|
+ if (accumulatedTotal > 0)
|
|
|
+ {
|
|
|
+ stats.total_overproofrate = (100 * accumulatedOverproof) / accumulatedTotal;
|
|
|
+ stats.total_overproofrate_alert = (100 * accumulatedOverproofAlert) / accumulatedTotal;
|
|
|
+ stats.total_overproofrate_2 = (100 * accumulatedOverproof2) / accumulatedTotal;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ stats.total_overproofrate = 0;
|
|
|
+ stats.total_overproofrate_alert = 0;
|
|
|
+ stats.total_overproofrate_2 = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取所有有数据的油枪 ID 列表
|
|
|
+ /// </summary>
|
|
|
+ public async Task<List<int>> GetAllNozzleIdsAsync()
|
|
|
+ {
|
|
|
+ var nozzles = await _prewarning.AsQueryable()
|
|
|
+ .Select(p => p.nozzle)
|
|
|
+ .Distinct()
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ return nozzles;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取统计日期范围(最早到最新)
|
|
|
+ /// </summary>
|
|
|
+ public async Task<(DateOnly minDate, DateOnly maxDate)> GetDateRangeAsync()
|
|
|
+ {
|
|
|
+ var dates = await _prewarning.AsQueryable()
|
|
|
+ .Select(p => p.date)
|
|
|
+ .ToListAsync();
|
|
|
+
|
|
|
+ if (dates == null || dates.Count == 0)
|
|
|
+ {
|
|
|
+ return (new DateOnly(), new DateOnly());
|
|
|
+ }
|
|
|
+
|
|
|
+ var minDate = dates.Min();
|
|
|
+ var maxDate = dates.Max();
|
|
|
+
|
|
|
+ return (minDate, maxDate);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|