version 3

This commit is contained in:
2025-12-17 00:34:41 +03:30
parent 139924db94
commit 74e8480a68
38 changed files with 5399 additions and 70 deletions

View File

@@ -0,0 +1,185 @@
using GreenHome.Application;
using Microsoft.EntityFrameworkCore;
namespace GreenHome.Infrastructure;
public sealed class MonthlyReportService : IMonthlyReportService
{
private readonly GreenHomeDbContext _context;
public MonthlyReportService(GreenHomeDbContext context)
{
_context = context;
}
public async Task<MonthlyReportDto> GetMonthlyReportAsync(
int deviceId,
int year,
int month,
CancellationToken cancellationToken)
{
var device = await _context.Devices
.FirstOrDefaultAsync(d => d.Id == deviceId, cancellationToken);
if (device == null)
{
throw new InvalidOperationException($"دستگاه با شناسه {deviceId} یافت نشد");
}
// Get alert logs for the month
var alertLogs = await _context.AlertLogs
.Where(al => al.DeviceId == deviceId &&
al.SentAt.Year == year &&
al.SentAt.Month == month)
.ToListAsync(cancellationToken);
var totalAlerts = alertLogs.Count;
var smsAlerts = alertLogs.Count(al => al.NotificationType == Domain.AlertNotificationType.SMS);
var callAlerts = alertLogs.Count(al => al.NotificationType == Domain.AlertNotificationType.Call);
var successfulAlerts = alertLogs.Count(al => al.Status == Domain.AlertStatus.Success);
var failedAlerts = alertLogs.Count(al => al.Status == Domain.AlertStatus.Failed);
var powerOutageAlerts = alertLogs.Count(al => al.AlertType == Domain.AlertType.PowerOutage);
// Get telemetry statistics
var telemetryData = await _context.TelemetryRecords
.Where(t => t.DeviceId == deviceId &&
t.PersianYear == year &&
t.PersianMonth == month)
.ToListAsync(cancellationToken);
var totalTelemetryRecords = telemetryData.Count;
var avgTemp = telemetryData.Any() ? telemetryData.Average(t => t.TemperatureC) : 0;
var minTemp = telemetryData.Any() ? telemetryData.Min(t => t.TemperatureC) : 0;
var maxTemp = telemetryData.Any() ? telemetryData.Max(t => t.TemperatureC) : 0;
var avgHumidity = telemetryData.Any() ? telemetryData.Average(t => t.HumidityPercent) : 0;
var minHumidity = telemetryData.Any() ? telemetryData.Min(t => t.HumidityPercent) : 0;
var maxHumidity = telemetryData.Any() ? telemetryData.Max(t => t.HumidityPercent) : 0;
var avgLux = telemetryData.Any() ? telemetryData.Average(t => t.Lux) : 0;
var avgGas = telemetryData.Any() ? (int)telemetryData.Average(t => t.GasPPM) : 0;
var maxGas = telemetryData.Any() ? telemetryData.Max(t => t.GasPPM) : 0;
// Get user activity
var userReportsCount = await _context.UserDailyReports
.CountAsync(r => r.DeviceId == deviceId &&
r.PersianYear == year &&
r.PersianMonth == month,
cancellationToken);
var checklistCompletionsCount = await _context.ChecklistCompletions
.Where(cc => cc.Checklist.DeviceId == deviceId)
.CountAsync(cc => cc.PersianDate.StartsWith($"{year}/{month:D2}"), cancellationToken);
var dailyAnalysesCount = await _context.DailyReports
.CountAsync(dr => dr.DeviceId == deviceId &&
dr.PersianYear == year &&
dr.PersianMonth == month,
cancellationToken);
// Generate performance summary
var performanceSummary = GeneratePerformanceSummary(
totalTelemetryRecords,
totalAlerts,
successfulAlerts,
failedAlerts,
avgTemp,
avgHumidity,
avgLux,
avgGas,
userReportsCount,
checklistCompletionsCount);
return new MonthlyReportDto
{
DeviceId = deviceId,
DeviceName = device.DeviceName,
Year = year,
Month = month,
TotalAlerts = totalAlerts,
SmsAlerts = smsAlerts,
CallAlerts = callAlerts,
SuccessfulAlerts = successfulAlerts,
FailedAlerts = failedAlerts,
PowerOutageAlerts = powerOutageAlerts,
TotalTelemetryRecords = totalTelemetryRecords,
AverageTemperature = avgTemp,
MinTemperature = minTemp,
MaxTemperature = maxTemp,
AverageHumidity = avgHumidity,
MinHumidity = minHumidity,
MaxHumidity = maxHumidity,
AverageLux = avgLux,
AverageGasPPM = avgGas,
MaxGasPPM = maxGas,
UserDailyReportsCount = userReportsCount,
ChecklistCompletionsCount = checklistCompletionsCount,
DailyAnalysesCount = dailyAnalysesCount,
PerformanceSummary = performanceSummary,
GeneratedAt = DateTime.UtcNow
};
}
private string GeneratePerformanceSummary(
int totalRecords,
int totalAlerts,
int successfulAlerts,
int failedAlerts,
decimal avgTemp,
decimal avgHumidity,
decimal avgLux,
int avgGas,
int userReports,
int checklistCompletions)
{
var summary = new List<string>();
summary.Add($"📊 آمار کلی:");
summary.Add($" • تعداد رکوردهای ثبت شده: {totalRecords:N0}");
summary.Add($" • میانگین دما: {avgTemp:F1}°C");
summary.Add($" • میانگین رطوبت: {avgHumidity:F1}%");
summary.Add($" • میانگین نور: {avgLux:F0} لوکس");
if (avgGas > 0)
summary.Add($" • میانگین CO: {avgGas} PPM");
summary.Add("");
summary.Add($"🚨 هشدارها:");
summary.Add($" • تعداد کل: {totalAlerts}");
summary.Add($" • موفق: {successfulAlerts}");
if (failedAlerts > 0)
summary.Add($" • ناموفق: {failedAlerts} ⚠️");
if (userReports > 0 || checklistCompletions > 0)
{
summary.Add("");
summary.Add($"📝 فعالیت کاربران:");
if (userReports > 0)
summary.Add($" • گزارش‌های روزانه: {userReports}");
if (checklistCompletions > 0)
summary.Add($" • تکمیل چک‌لیست: {checklistCompletions}");
}
// Performance rating
summary.Add("");
var rating = CalculatePerformanceRating(totalRecords, failedAlerts, totalAlerts);
summary.Add($"⭐ ارزیابی کلی: {rating}");
return string.Join("\n", summary);
}
private string CalculatePerformanceRating(int totalRecords, int failedAlerts, int totalAlerts)
{
if (totalRecords == 0)
return "بدون داده";
var failureRate = totalAlerts > 0 ? (double)failedAlerts / totalAlerts : 0;
if (failureRate == 0 && totalRecords > 1000)
return "عالی ✅";
else if (failureRate < 0.1 && totalRecords > 500)
return "خوب 👍";
else if (failureRate < 0.3)
return "متوسط ⚠️";
else
return "نیاز به بررسی 🔧";
}
}