Organization_Management #142
@ -9,6 +9,7 @@ namespace Marco.Pms.Model.ViewModels.AttendanceVM
|
|||||||
public string? FirstName { get; set; }
|
public string? FirstName { get; set; }
|
||||||
public string? LastName { get; set; }
|
public string? LastName { get; set; }
|
||||||
public string? EmployeeAvatar { get; set; }
|
public string? EmployeeAvatar { get; set; }
|
||||||
|
public string? OrganizationName { get; set; }
|
||||||
public DateTime? CheckInTime { get; set; }
|
public DateTime? CheckInTime { get; set; }
|
||||||
public DateTime? CheckOutTime { get; set; }
|
public DateTime? CheckOutTime { get; set; }
|
||||||
public string? JobRoleName { get; set; }
|
public string? JobRoleName { get; set; }
|
||||||
|
@ -143,12 +143,21 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
/// <param name="projectId">ProjectID</param>
|
/// <param name="projectId">ProjectID</param>
|
||||||
/// <param name="date">YYYY-MM-dd</param>
|
/// <param name="date">YYYY-MM-dd</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
||||||
[HttpGet("project/log")]
|
[HttpGet("project/log")]
|
||||||
|
|
||||||
public async Task<IActionResult> EmployeeAttendanceByDateRange([FromQuery] Guid projectId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
public async Task<IActionResult> EmployeeAttendanceByDateRange([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] string? dateFrom = null, [FromQuery] string? dateTo = null)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
Guid tenantId = GetTenantId();
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
|
||||||
|
var project = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||||
|
if (project == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Project {ProjectId} not found in database", projectId);
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Project not found."));
|
||||||
|
}
|
||||||
|
|
||||||
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, LoggedInEmployee.Id);
|
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, LoggedInEmployee.Id);
|
||||||
var hasSelfAttendancePermission = await _permission.HasPermission(PermissionsMaster.SelfAttendance, LoggedInEmployee.Id);
|
var hasSelfAttendancePermission = await _permission.HasPermission(PermissionsMaster.SelfAttendance, LoggedInEmployee.Id);
|
||||||
var hasProjectPermission = await _permission.HasProjectPermission(LoggedInEmployee, projectId);
|
var hasProjectPermission = await _permission.HasProjectPermission(LoggedInEmployee, projectId);
|
||||||
@ -188,10 +197,10 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
if (hasTeamAttendancePermission)
|
if (hasTeamAttendancePermission)
|
||||||
{
|
{
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == TenantId).ToListAsync();
|
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(TenantId, projectId, true);
|
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(tenantId, projectId, organizationId, true);
|
||||||
var jobRole = await _context.JobRoles.ToListAsync();
|
var jobRole = await _context.JobRoles.ToListAsync();
|
||||||
foreach (Attendance? attendance in lstAttendance)
|
foreach (Attendance? attendance in lstAttendance)
|
||||||
{
|
{
|
||||||
@ -212,12 +221,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
result1.FirstName = teamMember.Employee.FirstName;
|
result1.FirstName = teamMember.Employee.FirstName;
|
||||||
result1.LastName = teamMember.Employee.LastName;
|
result1.LastName = teamMember.Employee.LastName;
|
||||||
result1.JobRoleName = teamMember.Employee.JobRole != null ? teamMember.Employee.JobRole.Name : null;
|
result1.JobRoleName = teamMember.Employee.JobRole != null ? teamMember.Employee.JobRole.Name : null;
|
||||||
|
result1.OrganizationName = teamMember.Employee.Organization?.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result1.FirstName = null;
|
result1.FirstName = null;
|
||||||
result1.LastName = null;
|
result1.LastName = null;
|
||||||
result1.JobRoleName = null;
|
result1.JobRoleName = null;
|
||||||
|
result1.OrganizationName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(result1);
|
result.Add(result1);
|
||||||
@ -227,8 +238,22 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
}
|
}
|
||||||
else if (hasSelfAttendancePermission)
|
else if (hasSelfAttendancePermission)
|
||||||
{
|
{
|
||||||
List<Attendance> lstAttendances = await _context.Attendes.Where(c => c.ProjectID == projectId && c.EmployeeID == LoggedInEmployee.Id && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == TenantId).ToListAsync();
|
List<Attendance> lstAttendances = await _context.Attendes
|
||||||
ProjectAllocation? projectAllocation = await _context.ProjectAllocations.Include(pa => pa.Employee).FirstOrDefaultAsync(pa => pa.ProjectId == projectId && pa.EmployeeId == LoggedInEmployee.Id && pa.TenantId == TenantId && pa.IsActive);
|
.Where(c => c.ProjectID == projectId && c.EmployeeID == LoggedInEmployee.Id && c.AttendanceDate.Date >= fromDate.Date && c.AttendanceDate.Date <= toDate.Date && c.TenantId == tenantId)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var projectAllocationQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Where(pa => pa.ProjectId == projectId && pa.EmployeeId == LoggedInEmployee.Id && pa.TenantId == tenantId && pa.IsActive);
|
||||||
|
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync();
|
||||||
|
|
||||||
foreach (var attendance in lstAttendances)
|
foreach (var attendance in lstAttendances)
|
||||||
{
|
{
|
||||||
if (projectAllocation != null)
|
if (projectAllocation != null)
|
||||||
@ -241,6 +266,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
FirstName = projectAllocation.Employee?.FirstName,
|
FirstName = projectAllocation.Employee?.FirstName,
|
||||||
LastName = projectAllocation.Employee?.LastName,
|
LastName = projectAllocation.Employee?.LastName,
|
||||||
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
||||||
|
OrganizationName = projectAllocation.Employee?.Organization?.Name,
|
||||||
CheckInTime = attendance.InTime,
|
CheckInTime = attendance.InTime,
|
||||||
CheckOutTime = attendance.OutTime,
|
CheckOutTime = attendance.OutTime,
|
||||||
Activity = attendance.Activity
|
Activity = attendance.Activity
|
||||||
@ -253,118 +279,79 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="projectId">ProjectID</param>
|
|
||||||
/// <param name="date">YYYY-MM-dd</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpGet("project/team")]
|
[HttpGet("project/team")]
|
||||||
public async Task<IActionResult> EmployeeAttendanceByProject([FromQuery] Guid projectId, [FromQuery] bool IncludeInActive, [FromQuery] string? date = null)
|
/// <summary>
|
||||||
|
/// Retrieves employee attendance records for a specified project and date.
|
||||||
|
/// The result is filtered based on the logged-in employee's permissions (Team or Self).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projectId">The ID of the project.</param>
|
||||||
|
/// <param name="organizationId">Optional. Filters attendance for employees of a specific organization.</param>
|
||||||
|
/// <param name="includeInactive">Optional. Includes inactive employees in the team list if true.</param>
|
||||||
|
/// <param name="date">Optional. The date for which to fetch attendance, in "yyyy-MM-dd" format. Defaults to the current UTC date.</param>
|
||||||
|
/// <returns>An IActionResult containing a list of employee attendance records or an error response.</returns>
|
||||||
|
public async Task<IActionResult> EmployeeAttendanceByProjectAsync([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] bool includeInactive, [FromQuery] string? date = null)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
var tenantId = GetTenantId();
|
||||||
var LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, LoggedInEmployee.Id);
|
|
||||||
var hasSelfAttendancePermission = await _permission.HasPermission(PermissionsMaster.SelfAttendance, LoggedInEmployee.Id);
|
|
||||||
var hasProjectPermission = await _permission.HasProjectPermission(LoggedInEmployee, projectId);
|
|
||||||
|
|
||||||
if (!hasProjectPermission)
|
// --- 1. Initial Validation and Permission Checks ---
|
||||||
|
_logger.LogInfo("Fetching attendance for ProjectId: {ProjectId}, TenantId: {TenantId}", projectId, tenantId);
|
||||||
|
|
||||||
|
// Validate date format
|
||||||
|
if (!DateTime.TryParse(date, out var forDate))
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Employee {EmployeeId} tries to access attendance of project {ProjectId}, but don't have access", LoggedInEmployee.Id, projectId);
|
forDate = DateTime.UtcNow.Date; // Default to today's date
|
||||||
return Unauthorized(ApiResponse<object>.ErrorResponse("Unauthorized access", "Unauthorized access", 404));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime forDate = new DateTime();
|
// Check if the project exists and if the employee has access
|
||||||
|
var project = await _context.Projects.AsNoTracking().FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||||
if (date != null && DateTime.TryParse(date, out forDate) == false)
|
if (project == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("User sent Invalid Date while featching attendance logs");
|
_logger.LogWarning("Project {ProjectId} not found in database", projectId);
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Date", "Invalid Date", 400));
|
return NotFound(ApiResponse<object>.ErrorResponse("Project not found."));
|
||||||
|
|
||||||
}
|
|
||||||
if (projectId == Guid.Empty)
|
|
||||||
{
|
|
||||||
_logger.LogWarning("The project Id sent by user is less than or equal to zero");
|
|
||||||
return BadRequest(ApiResponse<object>.ErrorResponse("Project ID is required and must be greater than zero.", "Project ID is required and must be greater than zero.", 400));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new List<EmployeeAttendanceVM>();
|
if (!await _permission.HasProjectPermission(loggedInEmployee, projectId))
|
||||||
Attendance? attendance = null;
|
|
||||||
|
|
||||||
if (date == null) forDate = DateTime.UtcNow.Date;
|
|
||||||
if (hasTeamAttendancePermission)
|
|
||||||
{
|
{
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date == forDate && c.TenantId == TenantId).ToListAsync();
|
_logger.LogWarning("Unauthorized access attempt by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}", loggedInEmployee.Id, projectId);
|
||||||
|
return Unauthorized(ApiResponse<object>.ErrorResponse("You do not have permission to access this project."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 2. Delegate to Specific Logic Based on Permissions ---
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var hasTeamAttendancePermission = await _permission.HasPermission(PermissionsMaster.TeamAttendance, loggedInEmployee.Id);
|
||||||
|
List<EmployeeAttendanceVM> result;
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(TenantId, projectId, IncludeInActive);
|
if (hasTeamAttendancePermission)
|
||||||
var idList = projectteam.Select(p => p.EmployeeId).ToList();
|
|
||||||
//var emp = await _context.Employees.Where(e => idList.Contains(e.Id)).Include(e => e.JobRole).ToListAsync();
|
|
||||||
var jobRole = await _context.JobRoles.ToListAsync();
|
|
||||||
|
|
||||||
foreach (ProjectAllocation teamMember in projectteam)
|
|
||||||
{
|
{
|
||||||
if (teamMember.Employee != null && teamMember.Employee.JobRole != null)
|
_logger.LogInfo("EmployeeId: {EmployeeId} has Team Attendance permission. Fetching team attendance.", loggedInEmployee.Id);
|
||||||
{
|
result = await GetTeamAttendanceAsync(tenantId, projectId, organizationId, forDate, includeInactive);
|
||||||
var result1 = new EmployeeAttendanceVM()
|
}
|
||||||
{
|
else if (await _permission.HasPermission(PermissionsMaster.SelfAttendance, loggedInEmployee.Id))
|
||||||
EmployeeAvatar = null,
|
{
|
||||||
EmployeeId = teamMember.EmployeeId,
|
_logger.LogInfo("EmployeeId: {EmployeeId} has Self Attendance permission. Fetching self attendance.", loggedInEmployee.Id);
|
||||||
FirstName = teamMember.Employee.FirstName,
|
result = await GetSelfAttendanceAsync(tenantId, projectId, loggedInEmployee.Id, organizationId, forDate);
|
||||||
LastName = teamMember.Employee.LastName,
|
}
|
||||||
JobRoleName = teamMember.Employee.JobRole.Name,
|
else
|
||||||
};
|
{
|
||||||
|
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId}. No valid attendance permission found.", loggedInEmployee.Id);
|
||||||
//var member = emp.Where(e => e.Id == teamMember.EmployeeId);
|
return StatusCode(403, ApiResponse<object>.ErrorResponse("You do not have permission to view attendance.", new { }, 403));
|
||||||
|
|
||||||
|
|
||||||
attendance = lstAttendance.Find(x => x.EmployeeID == teamMember.EmployeeId) ?? new Attendance();
|
|
||||||
if (attendance != null)
|
|
||||||
{
|
|
||||||
result1.Id = attendance.Id;
|
|
||||||
result1.CheckInTime = attendance.InTime;
|
|
||||||
result1.CheckOutTime = attendance.OutTime;
|
|
||||||
result1.Activity = attendance.Activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Add(result1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Sort(delegate (EmployeeAttendanceVM x, EmployeeAttendanceVM y)
|
_logger.LogInfo("Successfully fetched {Count} attendance records for ProjectId: {ProjectId}", result.Count, projectId);
|
||||||
{
|
return Ok(ApiResponse<object>.SuccessResponse(result, $"{result.Count} attendance records fetched successfully."));
|
||||||
//return x.FirstName.CompareTo(y.FirstName);
|
|
||||||
return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else if (hasSelfAttendancePermission)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Attendance lstAttendance = await _context.Attendes.FirstOrDefaultAsync(c => c.ProjectID == projectId && c.EmployeeID == LoggedInEmployee.Id && c.AttendanceDate.Date == forDate && c.TenantId == TenantId) ?? new Attendance();
|
_logger.LogError(ex, "An error occurred while fetching attendance for ProjectId: {ProjectId}", projectId);
|
||||||
ProjectAllocation? projectAllocation = await _context.ProjectAllocations.Include(pa => pa.Employee).FirstOrDefaultAsync(pa => pa.ProjectId == projectId && pa.EmployeeId == LoggedInEmployee.Id && pa.TenantId == TenantId && pa.IsActive);
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("An internal server error occurred."));
|
||||||
if (projectAllocation != null)
|
|
||||||
{
|
|
||||||
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
|
||||||
{
|
|
||||||
Id = lstAttendance.Id,
|
|
||||||
EmployeeAvatar = null,
|
|
||||||
EmployeeId = projectAllocation.EmployeeId,
|
|
||||||
FirstName = projectAllocation.Employee?.FirstName,
|
|
||||||
LastName = projectAllocation.Employee?.LastName,
|
|
||||||
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
|
||||||
CheckInTime = lstAttendance.InTime,
|
|
||||||
CheckOutTime = lstAttendance.OutTime,
|
|
||||||
Activity = lstAttendance.Activity
|
|
||||||
};
|
|
||||||
result.Add(result1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_logger.LogInfo("{count} Attendance records fetched successfully", result.Count);
|
|
||||||
|
|
||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("regularize")]
|
[HttpGet("regularize")]
|
||||||
public async Task<IActionResult> GetRequestRegularizeAttendance([FromQuery] Guid projectId, [FromQuery] bool IncludeInActive)
|
public async Task<IActionResult> GetRequestRegularizeAttendance([FromQuery] Guid projectId, [FromQuery] Guid? organizationId, [FromQuery] bool IncludeInActive)
|
||||||
{
|
{
|
||||||
Guid TenantId = GetTenantId();
|
Guid TenantId = GetTenantId();
|
||||||
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
Employee LoggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
@ -379,7 +366,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
|
|
||||||
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.TenantId == TenantId).ToListAsync();
|
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE && c.TenantId == TenantId).ToListAsync();
|
||||||
|
|
||||||
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(TenantId, projectId, true);
|
List<ProjectAllocation> projectteam = await _projectServices.GetTeamByProject(TenantId, projectId, organizationId, true);
|
||||||
var idList = projectteam.Select(p => p.EmployeeId).ToList();
|
var idList = projectteam.Select(p => p.EmployeeId).ToList();
|
||||||
var jobRole = await _context.JobRoles.ToListAsync();
|
var jobRole = await _context.JobRoles.ToListAsync();
|
||||||
|
|
||||||
@ -402,6 +389,7 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
result1.FirstName = teamMember.Employee.FirstName;
|
result1.FirstName = teamMember.Employee.FirstName;
|
||||||
result1.LastName = teamMember.Employee.LastName;
|
result1.LastName = teamMember.Employee.LastName;
|
||||||
result1.JobRoleName = teamMember.Employee.JobRole.Name;
|
result1.JobRoleName = teamMember.Employee.JobRole.Name;
|
||||||
|
result1.OrganizationName = teamMember.Employee.Organization?.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Add(result1);
|
result.Add(result1);
|
||||||
@ -415,7 +403,6 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
return Ok(ApiResponse<object>.SuccessResponse(result, System.String.Format("{0} Attendance records fetched successfully", result.Count), 200));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("record")]
|
[Route("record")]
|
||||||
public async Task<IActionResult> RecordAttendance([FromBody] RecordAttendanceDot recordAttendanceDot)
|
public async Task<IActionResult> RecordAttendance([FromBody] RecordAttendanceDot recordAttendanceDot)
|
||||||
@ -823,5 +810,110 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
DateTime finalDateTime = new DateTime(date.Year, date.Month, date.Day, parsedTime.Hour, parsedTime.Minute, 0);
|
DateTime finalDateTime = new DateTime(date.Year, date.Month, date.Day, parsedTime.Hour, parsedTime.Minute, 0);
|
||||||
return finalDateTime;
|
return finalDateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches attendance for an entire project team using a single, optimized database query.
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<EmployeeAttendanceVM>> GetTeamAttendanceAsync(Guid tenantId, Guid projectId, Guid? organizationId, DateTime forDate, bool includeInactive)
|
||||||
|
{
|
||||||
|
// This single query joins ProjectAllocations with Employees and performs a LEFT JOIN with Attendances.
|
||||||
|
// This is far more efficient than fetching collections and joining them in memory.
|
||||||
|
var query = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Where(pa => pa.TenantId == tenantId && pa.ProjectId == projectId);
|
||||||
|
|
||||||
|
// Apply filters based on optional parameters
|
||||||
|
if (!includeInactive)
|
||||||
|
{
|
||||||
|
query = query.Where(pa => pa.IsActive);
|
||||||
|
}
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
query = query.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId).ToListAsync();
|
||||||
|
|
||||||
|
var teamAttendance = await query
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var response = teamAttendance
|
||||||
|
.Select(teamMember =>
|
||||||
|
{
|
||||||
|
var result1 = new EmployeeAttendanceVM()
|
||||||
|
{
|
||||||
|
EmployeeAvatar = null,
|
||||||
|
EmployeeId = teamMember.EmployeeId,
|
||||||
|
FirstName = teamMember.Employee?.FirstName,
|
||||||
|
LastName = teamMember.Employee?.LastName,
|
||||||
|
OrganizationName = teamMember.Employee?.Organization?.Name,
|
||||||
|
JobRoleName = teamMember.Employee?.JobRole?.Name,
|
||||||
|
};
|
||||||
|
|
||||||
|
//var member = emp.Where(e => e.Id == teamMember.EmployeeId);
|
||||||
|
|
||||||
|
|
||||||
|
var attendance = lstAttendance.Find(x => x.EmployeeID == teamMember.EmployeeId) ?? new Attendance();
|
||||||
|
if (attendance != null)
|
||||||
|
{
|
||||||
|
result1.Id = attendance.Id;
|
||||||
|
result1.CheckInTime = attendance.InTime;
|
||||||
|
result1.CheckOutTime = attendance.OutTime;
|
||||||
|
result1.Activity = attendance.Activity;
|
||||||
|
}
|
||||||
|
return result1;
|
||||||
|
})
|
||||||
|
.OrderBy(vm => vm.FirstName) // Let the database handle sorting.
|
||||||
|
.ThenBy(vm => vm.LastName).ToList();
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fetches a single attendance record for the logged-in employee.
|
||||||
|
/// </summary>
|
||||||
|
private async Task<List<EmployeeAttendanceVM>> GetSelfAttendanceAsync(Guid tenantId, Guid projectId, Guid employeeId, Guid? organizationId, DateTime forDate)
|
||||||
|
{
|
||||||
|
List<EmployeeAttendanceVM> result = new List<EmployeeAttendanceVM>();
|
||||||
|
|
||||||
|
// This query fetches the employee's project allocation and their attendance in a single trip.
|
||||||
|
Attendance lstAttendance = await _context.Attendes
|
||||||
|
.FirstOrDefaultAsync(c => c.ProjectID == projectId && c.EmployeeID == employeeId && c.AttendanceDate.Date == forDate && c.TenantId == tenantId) ?? new Attendance();
|
||||||
|
|
||||||
|
var projectAllocationQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Where(pa => pa.ProjectId == projectId && pa.EmployeeId == employeeId && pa.TenantId == tenantId && pa.IsActive);
|
||||||
|
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectAllocation = await projectAllocationQuery.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (projectAllocation != null)
|
||||||
|
{
|
||||||
|
EmployeeAttendanceVM result1 = new EmployeeAttendanceVM
|
||||||
|
{
|
||||||
|
Id = lstAttendance.Id,
|
||||||
|
EmployeeAvatar = null,
|
||||||
|
EmployeeId = projectAllocation.EmployeeId,
|
||||||
|
FirstName = projectAllocation.Employee?.FirstName,
|
||||||
|
OrganizationName = projectAllocation.Employee?.Organization?.Name,
|
||||||
|
LastName = projectAllocation.Employee?.LastName,
|
||||||
|
JobRoleName = projectAllocation.Employee?.JobRole?.Name,
|
||||||
|
CheckInTime = lstAttendance.InTime,
|
||||||
|
CheckOutTime = lstAttendance.OutTime,
|
||||||
|
Activity = lstAttendance.Activity
|
||||||
|
};
|
||||||
|
result.Add(result1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2298,21 +2298,22 @@ namespace Marco.Pms.Services.Service
|
|||||||
List<ProjectAllocation> alloc = await _context.ProjectAllocations.Where(c => c.EmployeeId == employeeId && c.IsActive == true).Include(c => c.Project).ToListAsync();
|
List<ProjectAllocation> alloc = await _context.ProjectAllocations.Where(c => c.EmployeeId == employeeId && c.IsActive == true).Include(c => c.Project).ToListAsync();
|
||||||
return alloc;
|
return alloc;
|
||||||
}
|
}
|
||||||
public async Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, bool IncludeInactive)
|
public async Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, Guid? OrganizationId, bool IncludeInactive)
|
||||||
{
|
{
|
||||||
if (IncludeInactive)
|
var projectAllocationQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.Organization)
|
||||||
|
.Where(pa => pa.TenantId == TenantId && pa.ProjectId == ProjectId);
|
||||||
|
if (!IncludeInactive)
|
||||||
{
|
{
|
||||||
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.IsActive);
|
||||||
var employees = await _context.ProjectAllocations.Where(c => c.TenantId == TenantId && c.ProjectId == ProjectId).Include(e => e.Employee).ToListAsync();
|
|
||||||
|
|
||||||
return employees;
|
|
||||||
}
|
}
|
||||||
else
|
if (OrganizationId.HasValue)
|
||||||
{
|
{
|
||||||
var employees = await _context.ProjectAllocations.Where(c => c.TenantId == TenantId && c.ProjectId == ProjectId && c.IsActive == true).Include(e => e.Employee).ToListAsync();
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == OrganizationId);
|
||||||
|
|
||||||
return employees;
|
|
||||||
}
|
}
|
||||||
|
var projectAllocation = await projectAllocationQuery.ToListAsync();
|
||||||
|
return projectAllocation;
|
||||||
}
|
}
|
||||||
public async Task<List<Guid>> GetMyProjects(Guid tenantId, Employee LoggedInEmployee)
|
public async Task<List<Guid>> GetMyProjects(Guid tenantId, Employee LoggedInEmployee)
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
|
|
||||||
Task<List<Project>> GetAllProjectByTanentID(Guid tanentId);
|
Task<List<Project>> GetAllProjectByTanentID(Guid tanentId);
|
||||||
Task<List<ProjectAllocation>> GetProjectByEmployeeID(Guid employeeId);
|
Task<List<ProjectAllocation>> GetProjectByEmployeeID(Guid employeeId);
|
||||||
Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, bool IncludeInactive);
|
Task<List<ProjectAllocation>> GetTeamByProject(Guid TenantId, Guid ProjectId, Guid? OrganizationId, bool IncludeInactive);
|
||||||
Task<List<Guid>> GetMyProjectIdsAsync(Guid tenantId, Employee LoggedInEmployee);
|
Task<List<Guid>> GetMyProjectIdsAsync(Guid tenantId, Employee LoggedInEmployee);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user