diff --git a/Marco.Pms.Services/Controllers/ReportController.cs b/Marco.Pms.Services/Controllers/ReportController.cs index 872f128..0191b7d 100644 --- a/Marco.Pms.Services/Controllers/ReportController.cs +++ b/Marco.Pms.Services/Controllers/ReportController.cs @@ -1,4 +1,5 @@ using Marco.Pms.DataAccess.Data; +using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Dtos.Mail; using Marco.Pms.Model.Mail; using Marco.Pms.Model.MongoDBModels.Utility; @@ -10,7 +11,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.CodeAnalysis; using Microsoft.EntityFrameworkCore; -using MongoDB.Driver; using System.Data; using System.Globalization; using System.Net.Mail; @@ -22,27 +22,25 @@ namespace Marco.Pms.Services.Controllers [Authorize] public class ReportController : ControllerBase { + private readonly IDbContextFactory _dbContextFactory; + private readonly IServiceScopeFactory _serviceScopeFactory; private readonly ApplicationDbContext _context; - private readonly IEmailSender _emailSender; private readonly ILoggingService _logger; private readonly UserHelper _userHelper; - private readonly IWebHostEnvironment _env; - private readonly ReportHelper _reportHelper; private readonly IConfiguration _configuration; - private readonly CacheUpdateHelper _cache; - private readonly IServiceScopeFactory _serviceScopeFactory; - public ReportController(ApplicationDbContext context, IEmailSender emailSender, ILoggingService logger, UserHelper userHelper, - IWebHostEnvironment env, ReportHelper reportHelper, IConfiguration configuration, CacheUpdateHelper cache, IServiceScopeFactory serviceScopeFactory) + public ReportController(IDbContextFactory dbContextFactory, + ApplicationDbContext context, + ILoggingService logger, + UserHelper userHelper, + IConfiguration configuration, + IServiceScopeFactory serviceScopeFactory) { - _context = context; - _emailSender = emailSender; - _logger = logger; - _userHelper = userHelper; - _env = env; - _reportHelper = reportHelper; - _configuration = configuration; - _cache = cache; - _serviceScopeFactory = serviceScopeFactory; + _dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory)); + _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); + _context = context ?? throw new ArgumentNullException(nameof(context)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _userHelper = userHelper ?? throw new ArgumentNullException(nameof(userHelper)); + _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); } /// @@ -435,10 +433,12 @@ namespace Marco.Pms.Services.Controllers 200)); } - [HttpGet("report-mail")] public async Task GetProjectStatisticsFromCache() { + using var scope = _serviceScopeFactory.CreateScope(); + var _cache = scope.ServiceProvider.GetRequiredService(); + var mailList = await _cache.GetProjectReportMail(false); if (mailList == null) { @@ -447,5 +447,65 @@ namespace Marco.Pms.Services.Controllers return Ok(ApiResponse.SuccessResponse(mailList, "Fetched list of mail body successfully", 200)); } + + [HttpGet("report-attendance")] + public async Task GetAttendanceReportAsync() + { + Guid tenantId = _userHelper.GetTenantId(); + using var scope = _serviceScopeFactory.CreateScope(); + + DateTime today = DateTime.Today; + DateTime firstDayOfMonth = new DateTime(today.Year, today.Month, 1); + DateTime firstDayOfNextMonth = firstDayOfMonth.AddMonths(1); + + // Generate list of all dates in the month + var allDates = Enumerable.Range(0, (firstDayOfNextMonth - firstDayOfMonth).Days) + .Select(offset => firstDayOfMonth.AddDays(offset)) + .ToList(); + + var attendances = await _context.Attendes + .Include(a => a.Employee) + .Where(a => a.AttendanceDate >= firstDayOfMonth && a.AttendanceDate < firstDayOfNextMonth && a.Employee != null && a.TenantId == tenantId) + .GroupBy(a => a.ProjectID) + .ToListAsync(); + + var result = attendances.Select(g => + { + return new + { + ProjectName = _context.Projects.Where(p => p.Id == g.Key && p.TenantId == tenantId).Select(p => p.Name).FirstOrDefault(), + ProjectAttendance = g.GroupBy(a => a.Employee).Select(gp => + { + var attendanceDate = gp.Select(a => a.AttendanceDate.Date).ToList(); + return new + { + FirstName = gp.Key!.FirstName, + LastName = gp.Key.LastName, + Attendances = allDates.Select(d => + { + var attendance = gp.FirstOrDefault(a => a.AttendanceDate.Date == d); + return new + { + AttendanceDate = d, + CheckIn = attendance?.InTime, + CheckOut = attendance?.OutTime, + Activity = attendance?.Activity, + IsApproved = attendance?.ApprovedById.HasValue, + }; + }).ToList(), + CheckInCheckOutDone = gp.Where(a => a.InTime.HasValue && a.OutTime.HasValue && a.Activity == ATTENDANCE_MARK_TYPE.REGULARIZE).Count(), + CheckInDone = gp.Where(a => a.InTime.HasValue).Count(), + CheckOutPending = gp.Where(a => a.InTime.HasValue && !a.OutTime.HasValue).Count(), + RejectedRegularize = gp.Where(a => a.Activity == ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT).Count(), + AbsentAttendance = allDates.Where(d => !attendanceDate.Contains(d) && d.DayOfWeek != DayOfWeek.Sunday).Count() + }; + }).OrderBy(ar => ar.FirstName).ThenBy(ar => ar.LastName).ToList() + }; + }).ToList(); + + var response = result.OrderBy(r => r.ProjectName).ToList(); + + return Ok(ApiResponse.SuccessResponse(response, "Attendance Report fetched successfully", 200)); + } } }