using Marco.Pms.DataAccess.Data; using Marco.Pms.Model.Activities; using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Projects; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels.DashBoard; using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Service; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Marco.Pms.Services.Controllers { [Authorize] [Route("api/[controller]")] [ApiController] public class DashboardController : ControllerBase { private readonly ApplicationDbContext _context; private readonly UserHelper _userHelper; private readonly ILoggingService _logger; public DashboardController(ApplicationDbContext context, UserHelper userHelper, ILoggingService logger) { _context = context; _userHelper = userHelper; _logger = logger; } [HttpGet("progression")] public async Task GetGraph([FromQuery] double days, [FromQuery] string FromDate, [FromQuery] Guid? projectId) { var tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); DateTime fromDate = new DateTime(); DateTime toDate = new DateTime(); List? projectProgressionVMs = new List(); if (FromDate != null && DateTime.TryParse(FromDate, out fromDate) == false) { return BadRequest(ApiResponse.ErrorResponse("Invalid starting date.", "Invalid starting date.", 400)); } var firstTask = await _context.TaskAllocations.Select(t => new { t.TenantId, t.AssignmentDate }).FirstOrDefaultAsync(t => t.TenantId == tenantId); if (FromDate == null) fromDate = DateTime.UtcNow.Date; if (firstTask == null) firstTask = new { TenantId = tenantId, AssignmentDate = DateTime.UtcNow }; if (days >= 0) { double negativeDays = 0 - days; toDate = fromDate.AddDays(negativeDays); if (firstTask != null && (firstTask.AssignmentDate.Date >= toDate.Date)) { toDate = firstTask.AssignmentDate; } if (projectId == null) { List tasks = await _context.TaskAllocations.Where(t => t.AssignmentDate.Date <= fromDate.Date && t.AssignmentDate.Date >= toDate.Date && t.TenantId == tenantId).ToListAsync(); double flagDays = 0; while (negativeDays < flagDays) { ProjectProgressionVM ProjectProgressionVM = new ProjectProgressionVM(); ProjectProgressionVM.ProjectId = projectId != null ? projectId.Value : Guid.Empty; ProjectProgressionVM.ProjectName = ""; var date = fromDate.AddDays(flagDays); if (date >= (firstTask != null ? firstTask.AssignmentDate.Date : null)) { var todayTasks = tasks.Where(t => t.AssignmentDate.Date == date.Date).ToList(); double plannedTaks = 0; double completedTasks = 0; ProjectProgressionVM.Date = date; foreach (var task in todayTasks) { plannedTaks += task.PlannedTask; completedTasks += task.CompletedTask; } ProjectProgressionVM.PlannedTask = plannedTaks; ProjectProgressionVM.CompletedTask = completedTasks; projectProgressionVMs.Add(ProjectProgressionVM); } flagDays -= 1; } _logger.LogInfo("Project Progression report for all projects fetched successfully by employee {EmployeeId}", LoggedInEmployee.Id); } else { var project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId); List buildings = await _context.Buildings.Where(b => b.ProjectId == projectId && b.TenantId == tenantId).ToListAsync(); List idList = buildings.Select(b => b.Id).ToList(); List floors = await _context.Floor.Where(f => idList.Contains(f.BuildingId) && f.TenantId == tenantId).ToListAsync(); idList = floors.Select(f => f.Id).ToList(); List workAreas = await _context.WorkAreas.Where(a => idList.Contains(a.FloorId) && a.TenantId == tenantId).ToListAsync(); idList = workAreas.Select(a => a.Id).ToList(); List workItems = await _context.WorkItems.Where(i => idList.Contains(i.WorkAreaId) && i.TenantId == tenantId).ToListAsync(); idList = workItems.Select(i => i.Id).ToList(); List tasks = await _context.TaskAllocations.Where(t => idList.Contains(t.WorkItemId) && t.AssignmentDate.Date <= fromDate.Date && t.AssignmentDate.Date >= toDate.Date && t.TenantId == tenantId).ToListAsync(); if (project != null) { double flagDays = 0; while (negativeDays < flagDays) { ProjectProgressionVM projectProgressionVM = new ProjectProgressionVM(); projectProgressionVM.ProjectId = projectId.Value; projectProgressionVM.ProjectName = project.Name; var date = fromDate.AddDays(flagDays); if (date >= (firstTask != null ? firstTask.AssignmentDate.Date : null)) { var todayTasks = tasks.Where(t => t.AssignmentDate.Date == date.Date).ToList(); double plannedTaks = 0; double completedTasks = 0; projectProgressionVM.Date = date; foreach (var task in todayTasks) { plannedTaks += task.PlannedTask; completedTasks += task.CompletedTask; } projectProgressionVM.PlannedTask = plannedTaks; projectProgressionVM.CompletedTask = completedTasks; projectProgressionVMs.Add(projectProgressionVM); } flagDays -= 1; } } _logger.LogInfo("Project Progression for project {ProjectId} fetched successfully by employee {EmployeeId}", projectId, LoggedInEmployee.Id); } } return Ok(ApiResponse.SuccessResponse(projectProgressionVMs, "Success", 200)); } [HttpGet("projects")] public async Task GetProjectCount() { var tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var projects = await _context.Projects.Where(p => p.TenantId == tenantId).ToListAsync(); var projectStatus = await _context.StatusMasters.Where(s => s.Status == "Active" || s.Status == "In Progress").ToListAsync(); var projectStatusIds = projectStatus.Select(s => s.Id).ToList(); var ongoingProjects = projects.Where(p => projectStatusIds.Contains(p.ProjectStatusId)).ToList(); ProjectDashboardVM projectDashboardVM = new ProjectDashboardVM { TotalProjects = projects.Count(), OngoingProjects = ongoingProjects.Count() }; _logger.LogInfo("Number of total ongoing projects fetched by employee {EmployeeId}", LoggedInEmployee.Id); return Ok(ApiResponse.SuccessResponse(projectDashboardVM, "Success", 200)); } [HttpGet("teams")] public async Task GetTotalEmployees() { var tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var date = DateTime.UtcNow.Date; var Employees = await _context.Employees.Where(e => e.TenantId == tenantId && e.IsActive == true).Select(e => e.Id).ToListAsync(); var checkedInEmployee = await _context.Attendes.Where(e => e.InTime != null ? e.InTime.Value.Date == date : false).Select(e => e.EmployeeID).ToListAsync(); TeamDashboardVM teamDashboardVM = new TeamDashboardVM { TotalEmployees = Employees.Count(), InToday = checkedInEmployee.Distinct().Count() }; _logger.LogInfo("Today's total checked in employees fetched by employee {EmployeeId}", LoggedInEmployee.Id); return Ok(ApiResponse.SuccessResponse(teamDashboardVM, "Success", 200)); } [HttpGet("tasks")] public async Task GetTotalTasks() { var tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var Tasks = await _context.WorkItems.Where(t => t.TenantId == tenantId).Select(t => new { PlannedWork = t.PlannedWork, CompletedWork = t.CompletedWork }).ToListAsync(); TasksDashboardVM tasksDashboardVM = new TasksDashboardVM { TotalTasks = 0, CompletedTasks = 0 }; foreach (var task in Tasks) { tasksDashboardVM.TotalTasks += task.PlannedWork; tasksDashboardVM.CompletedTasks += task.CompletedWork; } _logger.LogInfo("Total targeted tasks and total completed tasks fetched by employee {EmployeeId}", LoggedInEmployee.Id); return Ok(ApiResponse.SuccessResponse(tasksDashboardVM, "Success", 200)); } [HttpGet("pending-attendance")] public async Task GetPendingAttendance() { Guid tenantId = _userHelper.GetTenantId(); var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync(); var attendance = await _context.Attendes.Where(a => a.EmployeeID == LoggedInEmployee.Id && a.TenantId == tenantId).ToListAsync(); if (attendance.Any()) { var pendingRegularization = attendance.Where(a => a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE).ToList().Count; var pendingCheckOut = attendance.Where(a => a.OutTime == null).ToList().Count; var response = new { PendingRegularization = pendingRegularization, PendingCheckOut = pendingCheckOut }; _logger.LogInfo("Number of pending regularization and pending check-out are fetched successfully for employee {EmployeeId}", LoggedInEmployee.Id); return Ok(ApiResponse.SuccessResponse(response, "Pending regularization and pending check-out are fetched successfully", 200)); } _logger.LogError("No attendance entry was found for employee {EmployeeId}", LoggedInEmployee.Id); return NotFound(ApiResponse.ErrorResponse("No attendance entry was found for this employee", "No attendance entry was found for this employee", 404)); } } }