219 lines
12 KiB
C#
219 lines
12 KiB
C#
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<IActionResult> 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<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
|
}
|
|
if (id == Guid.Empty)
|
|
{
|
|
_logger.LogError("Provided empty project ID while fetching project report");
|
|
return BadRequest(ApiResponse<object>.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<object>.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> teamOnSite = new List<TeamOnSite>();
|
|
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<PerformedTask> performedTasks = new List<PerformedTask>();
|
|
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} </span><br/><span style=\"color: gray; font-size: small; padding-left: 10px;\"> {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<TaskTeam> Team = new List<TaskTeam>();
|
|
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<PerformedAttendance> performedAttendances = new List<PerformedAttendance>();
|
|
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<string> result = emails
|
|
.Split(';', StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(item => item.Trim())
|
|
.ToList();
|
|
await _emailSender.SendProjectStatisticsEmail(result, statisticReport);
|
|
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Email sent successfully", 200));
|
|
}
|
|
|
|
|
|
}
|
|
}
|