From f7e707557adab25717e90884e9449c19ec31a7f1 Mon Sep 17 00:00:00 2001 From: "ashutosh.nehete" Date: Mon, 8 Dec 2025 11:26:51 +0530 Subject: [PATCH] Optimized the get employee list API --- .../Controllers/DashboardController.cs | 65 +++----------- .../Controllers/EmployeeController.cs | 90 +++++++++---------- 2 files changed, 59 insertions(+), 96 deletions(-) diff --git a/Marco.Pms.Services/Controllers/DashboardController.cs b/Marco.Pms.Services/Controllers/DashboardController.cs index a68945b..d7294c6 100644 --- a/Marco.Pms.Services/Controllers/DashboardController.cs +++ b/Marco.Pms.Services/Controllers/DashboardController.cs @@ -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 { diff --git a/Marco.Pms.Services/Controllers/EmployeeController.cs b/Marco.Pms.Services/Controllers/EmployeeController.cs index 15da5d4..0555529 100644 --- a/Marco.Pms.Services/Controllers/EmployeeController.cs +++ b/Marco.Pms.Services/Controllers/EmployeeController.cs @@ -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.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 employees = new List(); - // 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(e)).Distinct().ToList();