using System.Globalization; using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Projects; using Marco.Pms.Model.Roles; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.Report; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using MongoDB.Driver; namespace Marco.Pms.Services.Controllers { [Route("api/[controller]")] [ApiController] [Authorize] public class ReportController : ControllerBase { private readonly ApplicationDbContext _context; private readonly IEmailSender _emailSender; private readonly IConfiguration _configuration; private readonly ILoggingService _logger; private readonly UserHelper _userHelper; public ReportController(ApplicationDbContext context, IEmailSender emailSender, IConfiguration configuration, ILoggingService logger, UserHelper userHelper) { _context = context; _emailSender = emailSender; _configuration = configuration; _logger = logger; _userHelper = userHelper; } [HttpGet("project-statistics/{id}")] public async Task GetProjectStatistics(Guid id, [FromQuery] string? date) { DateTime reportDate = DateTime.UtcNow; if (date != null && DateTime.TryParse(date, out reportDate) == false) { _logger.LogError("User sent Invalid from Date while featching project report"); return BadRequest(ApiResponse.ErrorResponse("Invalid Date", "Invalid Date", 400)); } if (id == Guid.Empty) { _logger.LogError("Provided empty project ID while fetching project report"); return BadRequest(ApiResponse.ErrorResponse("Provided empty ProjectID", "Provided empty ProjectID", 400)); } Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == id); if (project == null) { _logger.LogWarning("User attempted to fetch project progress of project ID {ProjectId} but not found in database", id); return NotFound(ApiResponse.ErrorResponse("Project not found", "Project not found", 404)); } ProjectStatisticReport statisticReport = new ProjectStatisticReport { Date = reportDate, ProjectName = project.Name ?? "", TimeStamp = DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss", CultureInfo.InvariantCulture) }; var projectAllocations = await _context.ProjectAllocations.Include(p => p.Employee).Where(p => p.ProjectId == project.Id && p.IsActive).ToListAsync(); var assignedEmployeeIds = projectAllocations.Select(p => p.EmployeeId).ToList(); var attendances = await _context.Attendes.AsNoTracking().Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date).ToListAsync(); var checkedInEmployeeIds = attendances.Select(p => p.EmployeeID).Distinct().ToList(); var checkedOutPendingEmployeeIds = attendances.Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date && a.OutTime == null).Select(p => p.EmployeeID).Distinct().ToList(); var regularizationEmployeeIds = attendances.Where(a => a.ProjectID == project.Id && a.InTime != null && a.InTime.Value.Date == reportDate.Date && a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE).Select(p => p.EmployeeID).Distinct().ToList(); var buildings = await _context.Buildings.Where(b => b.ProjectId == project.Id).ToListAsync(); var buildingIds = buildings.Select(b => b.Id).Distinct().ToList(); var floors = await _context.Floor.Where(f => buildingIds.Contains(f.BuildingId)).ToListAsync(); var floorIds = floors.Select(f => f.Id).Distinct().ToList(); var areas = await _context.WorkAreas.Where(a => floorIds.Contains(a.FloorId)).ToListAsync(); var areaIds = areas.Select(a => a.Id).Distinct().ToList(); var workItems = await _context.WorkItems.Include(i => i.ActivityMaster).Where(i => areaIds.Contains(i.WorkAreaId)).ToListAsync(); var itemIds = workItems.Select(i => i.Id).Distinct().ToList(); var tasks = await _context.TaskAllocations.Where(t => itemIds.Contains(t.WorkItemId)).ToListAsync(); var taskIds = tasks.Select(t => t.Id).Distinct().ToList(); var taskMembers = await _context.TaskMembers.Include(m => m.Employee).Where(m => taskIds.Contains(m.TaskAllocationId)).ToListAsync(); double totalPlannedWork = 0; double totalCompletedWork = 0; foreach (var items in workItems) { totalPlannedWork += items.PlannedWork; totalCompletedWork += items.CompletedWork; } var todayAssigned = tasks.Where(t => t.AssignmentDate.Date == reportDate.Date).ToList(); var reportPending = tasks.Where(t => t.ReportedDate == null).ToList(); double totalPlannedTask = 0; double totalCompletedTask = 0; foreach (var items in todayAssigned) { totalPlannedTask += items.PlannedTask; totalCompletedTask += items.CompletedTask; } var jobRoles = await _context.JobRoles.Where(r => r.TenantId == project.TenantId).ToListAsync(); List teamOnSite = new List(); foreach (var role in jobRoles) { int numberOfEmployees = 0; var roleassigned = projectAllocations.Where(p => p.JobRoleId == role.Id && checkedInEmployeeIds.Contains(p.EmployeeId)).ToList(); if (roleassigned.Count > 0) { numberOfEmployees = roleassigned.Count; } TeamOnSite team = new TeamOnSite { RoleName = role.Name, NumberofEmployees = numberOfEmployees, }; teamOnSite.Add(team); } List performedTasks = new List(); var todaysTask = tasks.Where(t => t.AssignmentDate.Date == reportDate.Date).ToList(); foreach (var task in todaysTask) { WorkItem workItem = workItems.FirstOrDefault(i => i.Id == task.WorkItemId) ?? new WorkItem(); string activityName = (workItem.ActivityMaster != null ? workItem.ActivityMaster.ActivityName : "") ?? ""; WorkArea workArea = areas.FirstOrDefault(a => a.Id == workItem.WorkAreaId) ?? new WorkArea(); string areaName = workArea.AreaName ?? ""; Floor floor = floors.FirstOrDefault(f => f.Id == workArea.FloorId) ?? new Floor(); string floorName = floor.FloorName ?? ""; Building building = buildings.FirstOrDefault(b => b.Id == floor.BuildingId) ?? new Building(); string buildingName = building.Name ?? ""; string location = $"{buildingName} > {floorName}
{floorName}-{areaName}"; double pending = workItem.PlannedWork - workItem.CompletedWork; PerformedTask performedTask = new PerformedTask { Activity = activityName, Location = location, AssignedToday = task.PlannedTask, Pending = pending, CompletedToday = task.CompletedTask, Comment = task.Description }; var taskTeams = taskMembers.Where(m => m.TaskAllocationId == task.Id).ToList(); List Team = new List(); foreach (var team in taskTeams) { string firstName = (team.Employee != null ? team.Employee.FirstName : "") ?? ""; string lastName = (team.Employee != null ? team.Employee.LastName : "") ?? ""; string name = $"{firstName} {lastName}"; JobRole role = jobRoles.FirstOrDefault(r => r.Id == (team.Employee != null ? team.Employee.JobRoleId : Guid.Empty)) ?? new JobRole(); string roleName = role.Name ?? ""; TaskTeam taskTeam = new TaskTeam { Name = name, RoleName = roleName, }; Team.Add(taskTeam); } performedTask.Team = Team; performedTasks.Add(performedTask); } List performedAttendances = new List(); foreach (var attendance in attendances) { ProjectAllocation projectAllocation = projectAllocations.FirstOrDefault(p => p.EmployeeId == attendance.EmployeeID) ?? new ProjectAllocation(); JobRole role = jobRoles.FirstOrDefault(r => r.Id == projectAllocation.JobRoleId) ?? new JobRole(); string firstName = (projectAllocation.Employee != null ? projectAllocation.Employee.FirstName : "") ?? ""; string lastName = (projectAllocation.Employee != null ? projectAllocation.Employee.LastName : "") ?? ""; string name = $"{firstName} {lastName}"; PerformedAttendance performedAttendance = new PerformedAttendance { Name = name, RoleName = role.Name ?? "", InTime = attendance.InTime ?? DateTime.UtcNow, OutTime = attendance.OutTime, Comment = attendance.Comment }; performedAttendances.Add(performedAttendance); } statisticReport.TodaysAttendances = checkedInEmployeeIds.Count; statisticReport.TotalEmployees = assignedEmployeeIds.Count; statisticReport.RegularizationPending = regularizationEmployeeIds.Count; statisticReport.CheckoutPending = checkedOutPendingEmployeeIds.Count; statisticReport.TotalPlannedWork = totalPlannedWork; statisticReport.TotalCompletedWork = totalCompletedWork; statisticReport.TotalPlannedTask = totalPlannedTask; statisticReport.TotalCompletedTask = totalCompletedTask; statisticReport.CompletionStatus = totalCompletedWork / totalPlannedWork; statisticReport.TodaysAssignTasks = todayAssigned.Count; statisticReport.ReportPending = reportPending.Count; statisticReport.TeamOnSite = teamOnSite.OrderByDescending(c => c.NumberofEmployees).ToList(); statisticReport.PerformedTasks = performedTasks; statisticReport.PerformedAttendance = performedAttendances; string emails = _configuration["MailingList:ProjectStatisticsReceivers"] ?? ""; List result = emails .Split(';', StringSplitOptions.RemoveEmptyEntries) .Select(item => item.Trim()) .ToList(); await _emailSender.SendProjectStatisticsEmail(result, statisticReport); return Ok(ApiResponse.SuccessResponse(new { }, "Email sent successfully", 200)); } } }