359 lines
19 KiB
C#

using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Activities;
using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Employees;
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<IActionResult> 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<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
if (FromDate != null && DateTime.TryParse(FromDate, out fromDate) == false)
{
return BadRequest(ApiResponse<object>.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<TaskAllocation> 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<Building> buildings = await _context.Buildings.Where(b => b.ProjectId == projectId && b.TenantId == tenantId).ToListAsync();
List<Guid> idList = buildings.Select(b => b.Id).ToList();
List<Floor> floors = await _context.Floor.Where(f => idList.Contains(f.BuildingId) && f.TenantId == tenantId).ToListAsync();
idList = floors.Select(f => f.Id).ToList();
List<WorkArea> workAreas = await _context.WorkAreas.Where(a => idList.Contains(a.FloorId) && a.TenantId == tenantId).ToListAsync();
idList = workAreas.Select(a => a.Id).ToList();
List<WorkItem> workItems = await _context.WorkItems.Where(i => idList.Contains(i.WorkAreaId) && i.TenantId == tenantId).ToListAsync();
idList = workItems.Select(i => i.Id).ToList();
List<TaskAllocation> 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<object>.SuccessResponse(projectProgressionVMs, "Success", 200));
}
[HttpGet("projects")]
public async Task<IActionResult> 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<object>.SuccessResponse(projectDashboardVM, "Success", 200));
}
[HttpGet("teams")]
public async Task<IActionResult> 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<object>.SuccessResponse(teamDashboardVM, "Success", 200));
}
[HttpGet("tasks")]
public async Task<IActionResult> 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<object>.SuccessResponse(tasksDashboardVM, "Success", 200));
}
[HttpGet("pending-attendance")]
public async Task<IActionResult> 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<object>.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<object>.ErrorResponse("No attendance entry was found for this employee", "No attendance entry was found for this employee", 404));
}
[HttpGet("project-attendance/{projectId}")]
public async Task<IActionResult> GetProjectAttendance(Guid projectId, [FromQuery] string? date)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
DateTime currentDate = DateTime.UtcNow;
List<ProjectProgressionVM>? projectProgressionVMs = new List<ProjectProgressionVM>();
if (date != null && DateTime.TryParse(date, out currentDate) == false)
{
_logger.LogError($"user send invalid date");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
}
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
if (project == null)
{
_logger.LogError("Employee {EmployeeId} was attempted to get project attendance for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
}
List<ProjectAllocation>? projectAllocation = await _context.ProjectAllocations.Where(p => p.ProjectId == projectId && p.IsActive && p.TenantId == tenantId).ToListAsync();
var employeeIds = projectAllocation.Select(p => p.EmployeeId).Distinct().ToList();
List<Employee>? employees = await _context.Employees.Where(e => employeeIds.Contains(e.Id)).ToListAsync();
var attendances = await _context.Attendes.Where(a => employeeIds.Contains(a.EmployeeID) && a.ProjectID == projectId && a.InTime.HasValue && a.InTime.Value.Date == currentDate.Date).ToListAsync();
List<EmployeeAttendanceVM> employeeAttendanceVMs = new List<EmployeeAttendanceVM>();
foreach (var attendance in attendances)
{
Employee? employee = employees.FirstOrDefault(e => e.Id == attendance.EmployeeID);
if (employee != null)
{
EmployeeAttendanceVM employeeAttendanceVM = new EmployeeAttendanceVM
{
FirstName = employee.FirstName,
LastName = employee.LastName,
MiddleName = employee.MiddleName,
Comment = attendance.Comment,
InTime = attendance.InTime ?? DateTime.UtcNow,
OutTime = attendance.OutTime ?? DateTime.UtcNow
};
employeeAttendanceVMs.Add(employeeAttendanceVM);
}
}
ProjectAttendanceVM projectAttendanceVM = new ProjectAttendanceVM();
projectAttendanceVM.AttendanceTable = employeeAttendanceVMs;
projectAttendanceVM.CheckedInEmployee = attendances.Count;
projectAttendanceVM.AssignedEmployee = employeeIds.Count;
_logger.LogInfo($"Attendance record for project {projectId} for date {currentDate.Date} by employee {LoggedInEmployee.Id}");
return Ok(ApiResponse<object>.SuccessResponse(projectAttendanceVM, $"Attendance record for project {project.Name} for date {currentDate.Date}", 200));
}
[HttpGet("activities/{projectId}")]
public async Task<IActionResult> GetActivities(Guid projectId, [FromQuery] string? date)
{
Guid tenantId = _userHelper.GetTenantId();
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
DateTime currentDate = DateTime.UtcNow;
if (date != null && DateTime.TryParse(date, out currentDate) == false)
{
_logger.LogError($"user send invalid date");
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid date.", "Invalid date.", 400));
}
Project? project = await _context.Projects.FirstOrDefaultAsync(p => p.Id == projectId);
if (project == null)
{
_logger.LogError("Employee {EmployeeId} was attempted to get activities performed for date {Date}, but project not found in database", LoggedInEmployee.Id, currentDate);
return NotFound(ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404));
}
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) && t.AssignmentDate.Date == currentDate.Date).ToListAsync();
double totalPlannedTask = 0;
double totalCompletedTask = 0;
List<PerformedActivites> performedActivites = new List<PerformedActivites>();
foreach (var task in tasks)
{
totalPlannedTask += task.PlannedTask;
totalCompletedTask += task.CompletedTask;
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 ?? "";
PerformedActivites performedTask = new PerformedActivites
{
ActivityName = activityName,
BuldingName = buildingName,
FloorName = floorName,
WorkAreaName = areaName,
AssignedToday = task.PlannedTask,
CompletedToday = task.CompletedTask,
};
performedActivites.Add(performedTask);
}
var pendingReport = tasks.Where(t => t.ReportedDate == null).ToList().Count;
ActivityReport report = new ActivityReport
{
PerformedActivites = performedActivites,
TotalCompletedWork = totalCompletedTask,
TotalPlannedWork = totalPlannedTask,
ReportPending = pendingReport,
TodaysAssigned = tasks.Count
};
_logger.LogInfo($"Record of performed activities for project {projectId} for date {currentDate.Date} by employee {LoggedInEmployee.Id}");
return Ok(ApiResponse<object>.SuccessResponse(report, $"Record of performed activities for project {project.Name} for date {currentDate.Date}", 200));
}
}
}