Optimized the get employee list API

This commit is contained in:
ashutosh.nehete 2025-12-08 11:26:51 +05:30
parent 6c35bd3bf8
commit f7e707557a
2 changed files with 59 additions and 96 deletions

View File

@ -4,7 +4,6 @@ using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Expenses;
using Marco.Pms.Model.OrganizationModel;
using Marco.Pms.Model.ServiceProject;
using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Activities;
using Marco.Pms.Model.ViewModels.AttendanceVM;
@ -1679,61 +1678,25 @@ namespace Marco.Pms.Services.Controllers
query = query.Where(jt => jt.ProjectId == projectId.Value);
}
var jobs = await query
.Select(jt => new
{
Id = jt.Id,
StatusId = jt.StatusId,
Project = jt.Project!.Name,
AssignedBy = jt.CreatedBy!.FirstName + " " + jt.CreatedBy.LastName,
Title = jt.Title,
AssignedAt = jt.CreatedAt,
})
.OrderByDescending(jt => jt.AssignedAt)
.ToListAsync();
var inProgressJobIds = jobs.Where(jt => jt.StatusId == InProgressStatus).Select(jt => jt.Id).ToList();
var latestTagIns = await _context.JobAttendance
.Include(ja => ja.Employee)
.Where(ja => inProgressJobIds.Contains(ja.JobTicketId)
&& ja.Action == TAGGING_MARK_TYPE.TAG_IN
&& ja.TaggedOutAt == null
&& ja.TenantId == tenantId)
.GroupBy(ja => ja.JobTicketId)
.Select(g => new
{
JobTicketId = g.Key,
Employee = g.Select(ja => ja.Employee).FirstOrDefault(),
TagInAt = g.Max(ja => ja.TaggedInAt)
})
.ToListAsync();
var assignedJobs = jobs.Where(jt => jt.StatusId == AssignedStatus).Take(5).OrderBy(jt => jt.Title).ToList();
var assignedJobs = jobs
.Where(jt => jt.StatusId == AssignedStatus)
.Take(5)
.Select(jt => new
{
Project = jt.Project!.Name,
AssignedBy = jt.CreatedBy!.FirstName + " " + jt.CreatedBy.LastName,
Title = jt.Title,
AssignedAt = jt.CreatedAt,
var inProgressJobs = jobs.Where(jt => jt.StatusId == InProgressStatus).Take(5).OrderBy(jt => jt.Title).ToList();
})
.ToList();
var inProgressJobs = jobs
.Where(jt => jt.StatusId == InProgressStatus)
.Take(5)
.Select(jt => new
{
Project = jt.Project!.Name,
AssignedBy = jt.CreatedBy!.FirstName + " " + jt.CreatedBy.LastName,
Title = jt.Title,
AssignedAt = jt.CreatedAt,
})
.ToList();
var selfAssignedJobs = jobs
.Where(jt => jobIds.Contains(jt.Id))
.Take(5)
.Select(jt => new
{
Project = jt.Project!.Name,
AssignedBy = jt.CreatedBy!.FirstName + " " + jt.CreatedBy.LastName,
Title = jt.Title,
AssignedAt = jt.CreatedAt,
})
.ToList();
var selfAssignedJobs = jobs.Where(jt => jobIds.Contains(jt.Id)).Take(5).OrderBy(jt => jt.Title).ToList();
var response = new
{

View File

@ -249,67 +249,67 @@ namespace MarcoBMS.Services.Controllers
var hasViewAllEmployeesPermission = viewAllTask.Result;
var hasViewTeamMembersPermission = viewTeamTask.Result;
if (!hasViewAllEmployeesPermission && !hasViewTeamMembersPermission)
{
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have permission to view employees", loggedInEmployee.Id);
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User does not have permission to view employees", 403));
}
var projectIds = await _projectServices.GetMyProjectIdsAsync(loggedInEmployee, tenantId);
var projectAllocationQuery = _context.ProjectAllocations
.AsNoTracking()
.Where(pa =>
projectIds.Contains(pa.ProjectId)
&& pa.IsActive
&& pa.TenantId == tenantId);
if (projectId.HasValue)
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.ProjectId == projectId);
var employeeIds = await projectAllocationQuery
.Select(pa => pa.EmployeeId)
.Distinct()
.ToListAsync();
List<Employee> employees = new List<Employee>();
// Step 4: Query based on permission
if (hasViewAllEmployeesPermission && !projectId.HasValue)
{
// OrganizationId needs to be retrieved from loggedInEmployee or context based on your app's structure
var employeeQuery = _context.Employees
var employeeQuery = _context.Employees
.AsNoTracking() // Optimize EF query for read-only operation[web:1][web:13][web:18]
.Include(e => e.JobRole)
.Where(e => e.OrganizationId == organizationId);
.Where(e => e.IsActive != showInactive);
employeeQuery = showInactive
? employeeQuery.Where(e => !e.IsActive)
: employeeQuery.Where(e => e.IsActive);
employees = await employeeQuery.ToListAsync();
// Step 4: Query based on permission
if (hasViewAllEmployeesPermission)
{
// OrganizationId needs to be retrieved from loggedInEmployee or context based on your app's structure
if (projectId.HasValue)
{
employeeQuery = employeeQuery
.Where(e => employeeIds.Contains(e.Id));
}
else
{
employeeQuery = employeeQuery
.Where(e => e.OrganizationId == organizationId || employeeIds.Contains(e.Id));
}
employees = await employeeQuery
.Distinct()
.ToListAsync();
_logger.LogInfo("Employee list fetched with full access. Count: {Count}", employees.Count);
}
else if (hasViewTeamMembersPermission && !showInactive && !projectId.HasValue)
else if (hasViewTeamMembersPermission && !showInactive)
{
// Only active team members with limited permission
var projectIds = await _projectServices.GetMyProjectIdsAsync(loggedInEmployee, tenantId);
employees = await _context.ProjectAllocations
.AsNoTracking()
.Include(pa => pa.Employee)
.ThenInclude(e => e!.JobRole)
.Where(pa =>
projectIds.Contains(pa.ProjectId)
&& pa.IsActive
&& pa.Employee != null
&& pa.Employee.IsActive
&& pa.TenantId == tenantId)
.Select(pa => pa.Employee!)
employees = await employeeQuery
.Where(e => employeeIds.Contains(e.Id))
.Distinct()
.ToListAsync();
_logger.LogInfo("Employee list fetched with limited access (active only). Count: {Count}", employees.Count);
}
// If a specific projectId is provided, override employee fetching to ensure strict project context
if (projectId.HasValue)
{
employees = await _context.ProjectAllocations
.AsNoTracking()
.Include(pa => pa.Employee)
.ThenInclude(e => e!.JobRole)
.Where(pa =>
pa.ProjectId == projectId
&& pa.IsActive
&& pa.Employee != null
&& pa.Employee.IsActive
&& pa.TenantId == tenantId)
.Select(pa => pa.Employee!)
.Distinct()
.ToListAsync();
_logger.LogInfo("Employee list fetched for specific project. ProjectId: {ProjectId}. Count: {Count}",
projectId, employees.Count);
}
// Step 5: Map to view model
result = employees.Select(e => _mapper.Map<EmployeeVM>(e)).Distinct().ToList();