using vendorApproverBackend.Data; using vendorApproverBackend.Enums; using vendorApproverBackend.Responses; using Microsoft.EntityFrameworkCore; using System.Globalization; public class StatsService { private readonly DataContext _context; public StatsService(DataContext context) { _context = context; } public async Task GetTotalEmployeesAsync() { return await _context.Users .CountAsync(u => u.Role == (RoleEnum)2); } public async Task GetTotalVendorsAsync() { return await _context.Users .CountAsync(u => u.Role == (RoleEnum)1); } public async Task GetActiveProductsCountAsync() { return await _context.Products .CountAsync(p => p.PrequalificationRequest.Status == RequestStatus.CERTIFIED); } public async Task GetUncertifiedProductsCountAsync() { return await _context.Products .CountAsync(p => p.PrequalificationRequest.Status != RequestStatus.CERTIFIED); } public async Task GetNewRequestsCountAsync() { return await _context.PrequalificationRequests .CountAsync(r => r.Status == RequestStatus.SUBMITTED); } public async Task GetPendingPaymentsCountAsync() { return await _context.PrequalificationRequests .CountAsync(r => r.Status == RequestStatus.DRAFT); } public async Task> GetPqRequestsStatusStatsAsync() { var statusCounts = await _context.PrequalificationRequests .GroupBy(r => r.Status) .Select(g => new PqRequestsStatusStats { Status = g.Key, Total = g.Count() }) .ToListAsync(); var allStats = Enum.GetValues(typeof(RequestStatus)) .Cast() .Select(status => statusCounts.FirstOrDefault(s => s.Status == status) ?? new PqRequestsStatusStats { Status = status, Total = 0 } ).ToList(); return allStats; } public async Task> GetCertifCountByLast5MonthsAsync() { var endDate = DateTime.UtcNow.Date.AddDays(1); var startDate = endDate.AddMonths(-5); var certs = await _context.Certifications .Where(c => c.Timestamp >= startDate && c.Timestamp < endDate) .ToListAsync(); var result = new List(); for (int i = 0; i < 5; i++) { var targetDate = DateTime.UtcNow.Date.AddMonths(-i); var monthStart = new DateTime(targetDate.Year, targetDate.Month, 1, 0, 0, 0, DateTimeKind.Utc); var nextMonthStart = monthStart.AddMonths(1); var count = certs .Count(c => c.Timestamp >= monthStart && c.Timestamp < nextMonthStart); result.Add(new CertificationDate { MonthName = monthStart.ToString("MMM yyyy"), CertifiedRequestsCount = count }); } return result.OrderBy(c => DateTime.ParseExact(c.MonthName, "MMM yyyy", System.Globalization.CultureInfo.InvariantCulture)).ToList(); } public async Task GetAdminStatsAsync() { var response = new AdminStatsResponse { TotalEmployees = await GetTotalEmployeesAsync(), TotalVendors = await GetTotalVendorsAsync(), ActiveProducts = await GetActiveProductsCountAsync(), UncertifiedProducts = await GetUncertifiedProductsCountAsync(), NewRequests = await GetNewRequestsCountAsync(), PendingPayments = await GetPendingPaymentsCountAsync(), PqRequestsStatusStats = await GetPqRequestsStatusStatsAsync(), CertifCountByLast5Months = await GetCertifCountByLast5MonthsAsync() }; var pendingStatuses = new List { RequestStatus.UNDER_REVIEW, RequestStatus.EVALUATION_COMPLETED, RequestStatus.INSPECTION, RequestStatus.FACTORY_VISIT }; response.PendingApprovals = response.PqRequestsStatusStats .Where(s => pendingStatuses.Contains(s.Status)) .Sum(s => s.Total); return response; } // --- Core Vendor Stats Methods --- public async Task GetVendorTotalRequestsAsync(long vendorId) { return await _context.PrequalificationRequests .CountAsync(r => r.VendorId == vendorId); } public async Task GetVendorActiveCertificationsCountAsync(long vendorId) { return await _context.Certifications .CountAsync(c => c.PrequalificationRequest.VendorId == vendorId && c.Status == CertificationStatus.ACTIVE); } public async Task GetVendorExpiredCertificationsCountAsync(long vendorId) { return await _context.Certifications .CountAsync(c => c.PrequalificationRequest.VendorId == vendorId && c.Status == CertificationStatus.EXPIRED); } public async Task GetVendorTotalPaymentsAmountAsync(long vendorId) { double? totalAmount = await _context.PaymentDetail .Where(pd => pd.PrequalificationRequest.VendorId == vendorId) .SumAsync(pd => (double?)pd.Amount); return totalAmount ?? 0.0; } public async Task> GetVendorPqRequestsStatusStatsAsync(long vendorId) { var statusCounts = await _context.PrequalificationRequests .Where(r => r.VendorId == vendorId) .GroupBy(r => r.Status) .Select(g => new PqRequestsStatusStats { Status = g.Key, Total = g.Count() }) .ToListAsync(); var allStats = Enum.GetValues(typeof(RequestStatus)) .Cast() .Select(status => statusCounts.FirstOrDefault(s => s.Status == status) ?? new PqRequestsStatusStats { Status = status, Total = 0 } ).ToList(); return allStats; } public async Task> GetVendorFactoryVisitStatsAsync(long vendorId) { var currentYear = DateTime.UtcNow.Year; var yearStart = new DateTime(currentYear, 1, 1, 0, 0, 0, DateTimeKind.Utc); var yearEnd = yearStart.AddYears(1); var visits = await _context.PrequalificationRequests .Where(r => r.VendorId == vendorId) .Select(r => r.VisitRequest) .Where(v => v != null && v.StartDate >= yearStart && v.StartDate < yearEnd) .Select(v => new { v.StartDate }) .ToListAsync(); var stats = new List(); var culture = CultureInfo.InvariantCulture; for (int month = 1; month <= 12; month++) { var monthName = new DateTime(currentYear, month, 1).ToString("MMM yyyy", culture); var visitDates = visits .Where(v => v.StartDate.Year == currentYear && v.StartDate.Month == month) .Select(v => v.StartDate) .OrderBy(d => d) .ToList(); stats.Add(new FactoryVisitStats { MonthName = monthName, VisitDates = visitDates }); } return stats; } public async Task GetVendorStatsAsync(long vendorId) { var response = new VendorStatsResponse { TotalRequests = await GetVendorTotalRequestsAsync(vendorId), TotalActiveCertifications = await GetVendorActiveCertificationsCountAsync(vendorId), TotalExpiredCertifications = await GetVendorExpiredCertificationsCountAsync(vendorId), TotalPaymentsAmount = await GetVendorTotalPaymentsAmountAsync(vendorId), PqRequestsStatusStats = await GetVendorPqRequestsStatusStatsAsync(vendorId), FactoryVisitStats = await GetVendorFactoryVisitStatsAsync(vendorId) }; return response; } // --- Core Employee Stats Methods --- public async Task GetEmployeeTotalRequestsAsync(long userId) { return await _context.PrequalificationRequests .CountAsync(r => r.AssignedToUserId == userId || r.Inspectors.Any(i => i.Id == userId) ); } public async Task GetEmployeeTotalApplicationsAsync(long userId) { return await _context.EmployeeApplications .CountAsync(a => a.UserId == userId); } public async Task GetEmployeeSubmittedApplicationsAsync(long userId) { return await _context.EmployeeApplications .CountAsync(a => a.UserId == userId && a.Status == ApplicationStatus.SUBMITTED); } public async Task GetEmployeeApprovedApplicationsAsync(long userId) { return await _context.EmployeeApplications .CountAsync(a => a.UserId == userId && a.Status == ApplicationStatus.APPROVED); } public async Task GetEmployeeRejectedApplicationsAsync(long userId) { return await _context.EmployeeApplications .CountAsync(a => a.UserId == userId && a.Status == ApplicationStatus.REJECTED); } public async Task> GetEmployeeRequestsStatsAsync(long userId) { var currentYear = DateTime.UtcNow.Year; var yearStart = new DateTime(currentYear, 1, 1, 0, 0, 0, DateTimeKind.Utc); var yearEnd = yearStart.AddYears(1); var requests = await _context.PrequalificationRequests .Where(r => (r.AssignedToUserId == userId || r.Inspectors.Any(i => i.Id == userId)) && r.Timestamp >= yearStart && r.Timestamp < yearEnd) .Select(r => new { r.Timestamp, IsAssigned = r.AssignedToUserId == userId, IsInspector = r.Inspectors.Any(i => i.Id == userId) }) .ToListAsync(); var stats = new List(); var culture = CultureInfo.InvariantCulture; for (int month = 1; month <= 12; month++) { var monthName = new DateTime(currentYear, month, 1).ToString("MMM yyyy", culture); var monthlyRequests = requests .Where(r => r.Timestamp.Year == currentYear && r.Timestamp.Month == month); stats.Add(new EmployeeRequestsStats { MonthName = monthName, TotalRequestsAsEvaluator = monthlyRequests.Count(r => r.IsAssigned), TotalRequestsAsInspector = monthlyRequests.Count(r => r.IsInspector) }); } return stats; } public async Task GetEmployeeStatsAsync(long userId) { var response = new EmployeeStatsResponse { TotalRequests = await GetEmployeeTotalRequestsAsync(userId), TotalApplications = await GetEmployeeTotalApplicationsAsync(userId), TotalSumittedApplications = await GetEmployeeSubmittedApplicationsAsync(userId), TotalApprovedApplications = await GetEmployeeApprovedApplicationsAsync(userId), TotalRejectedApplications = await GetEmployeeRejectedApplicationsAsync(userId), PqRequestsStatusStats = await GetEmployeeRequestsStatsAsync(userId) }; return response; } // --- Core Financial Stats Methods --- public async Task GetTotalPaymentsCountAsync() { return await _context.PaymentDetail.CountAsync(); } public async Task GetTotalPaymentsAmountAsync() { double? total = await _context.PaymentDetail.SumAsync(p => (double?)p.Amount); return total ?? 0.0; } public async Task> GetPaymentDetailsStatusStatsAsync() { var statusCounts = await _context.PaymentDetail .GroupBy(p => p.Status) .Select(g => new PaymentDetailsStatusStats { Status = g.Key, PaymentsCount = g.Count() }) .ToListAsync(); var allStats = Enum.GetValues(typeof(PaymentStatus)) .Cast() .Select(status => statusCounts.FirstOrDefault(s => s.Status == status) ?? new PaymentDetailsStatusStats { Status = status, PaymentsCount = 0 } ).ToList(); return allStats; } public async Task> GetPaymentDetailsByMonthStatsAsync() { var currentYear = DateTime.UtcNow.Year; var yearStart = new DateTime(currentYear, 1, 1, 0, 0, 0, DateTimeKind.Utc); var yearEnd = yearStart.AddYears(1); var payments = await _context.PaymentDetail .Where(p => p.PaymentDate >= yearStart && p.PaymentDate < yearEnd) .Select(p => new { p.PaymentDate, p.Amount }) .ToListAsync(); var stats = new List(); var culture = CultureInfo.InvariantCulture; for (int month = 1; month <= 12; month++) { var monthStart = new DateTime(currentYear, month, 1); var monthName = monthStart.ToString("MMM yyyy", culture); var totalAmount = payments .Where(p => p.PaymentDate.Year == currentYear && p.PaymentDate.Month == month) .Sum(p => p.Amount); stats.Add(new PaymentDetailsStats { MonthName = monthName, TotalPaymentAmount = totalAmount }); } return stats; } public async Task GetFinancialStatsAsync() { var response = new FinancialStatsResponse { TotalPaymentsCount = await GetTotalPaymentsCountAsync(), TotalPaymentsAmount = await GetTotalPaymentsAmountAsync(), PaymentDetailsStatusStats = await GetPaymentDetailsStatusStatsAsync(), PaymentDetailsStats = await GetPaymentDetailsByMonthStatsAsync() }; return response; } }