Merge pull request 'Added new API to get list of employees assigned to project and filtered by services and organizations' (#140) from Ashutosh_Task#1360 into Organization_Management
Reviewed-on: #140
This commit is contained in:
commit
eddbdde355
@ -319,6 +319,14 @@ namespace MarcoBMS.Services.Controllers
|
|||||||
return StatusCode(response.StatusCode, response);
|
return StatusCode(response.StatusCode, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("get/task/team/{projectId}")]
|
||||||
|
public async Task<IActionResult> GetProjectTeamByServiceAndOrganization(Guid projectId, [FromQuery] Guid? serviceId, [FromQuery] Guid? organizationId)
|
||||||
|
{
|
||||||
|
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
var response = await _projectServices.GetProjectTeamByServiceAndOrganizationAsync(projectId, serviceId, organizationId, tenantId, loggedInEmployee);
|
||||||
|
return StatusCode(response.StatusCode, response);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Project InfraStructure Get APIs ===================================================================
|
#region =================================================================== Project InfraStructure Get APIs ===================================================================
|
||||||
|
@ -1166,6 +1166,190 @@ namespace Marco.Pms.Services.Service
|
|||||||
500);
|
500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task<ApiResponse<object>> GetProjectTeamByServiceAndOrganization(Guid projectId, Guid? serviceId, Guid? organizationId, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
|
||||||
|
var projectTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await context.Projects.FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||||
|
});
|
||||||
|
|
||||||
|
var tenantTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(projectTask, tenantTask);
|
||||||
|
|
||||||
|
var project = projectTask.Result;
|
||||||
|
var tenant = tenantTask.Result;
|
||||||
|
|
||||||
|
if (project == null || tenant == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Project {ProjectId} not found in database for tenant {TenantId}", projectId, tenantId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Project not found", "Project not found", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the logged-in employee has permission for the requested project
|
||||||
|
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId);
|
||||||
|
if (!hasProjectPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("User {EmployeeId} attempts to get employees for project {ProjectId} without permission", loggedInEmployee.Id, projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access denied", "User does not have access to view the employees for this project", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
var organizationQuery = _context.ProjectOrgMappings
|
||||||
|
.Include(po => po.ProjectService)
|
||||||
|
.Where(po => po.ProjectService != null && po.ProjectService.ProjectId == projectId);
|
||||||
|
|
||||||
|
if (loggedInEmployee.OrganizationId != project.PMCId && loggedInEmployee.OrganizationId != project.PromoterId && loggedInEmployee.OrganizationId != tenant.OrganizationId)
|
||||||
|
{
|
||||||
|
organizationQuery = organizationQuery.Where(po => po.ParentOrganizationId == loggedInEmployee.OrganizationId || po.OrganizationId == loggedInEmployee.OrganizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var organizationIds = await organizationQuery.Select(po => po.OrganizationId).ToListAsync();
|
||||||
|
|
||||||
|
if (loggedInEmployee.OrganizationId == project.PMCId || loggedInEmployee.OrganizationId == project.PromoterId || loggedInEmployee.OrganizationId == tenant.OrganizationId)
|
||||||
|
{
|
||||||
|
organizationIds.Add(project.PMCId);
|
||||||
|
organizationIds.Add(project.PromoterId);
|
||||||
|
organizationIds.Add(tenant.OrganizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectAllocationQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(pa => pa.ProjectId == projectId && pa.Employee != null && organizationIds.Contains(pa.Employee.OrganizationId));
|
||||||
|
|
||||||
|
if (serviceId.HasValue)
|
||||||
|
{
|
||||||
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.ServiceId == serviceId);
|
||||||
|
}
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
projectAllocationQuery = projectAllocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectAllocations = await projectAllocationQuery
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var result = projectAllocations.Select(pa => _mapper.Map<EmployeeVM>(pa.Employee)).Distinct().ToList();
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(result, "Employee list fetched successfully", 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ApiResponse<object>> GetProjectTeamByServiceAndOrganizationAsync(
|
||||||
|
Guid projectId, Guid? serviceId, Guid? organizationId, Guid tenantId, Employee loggedInEmployee)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("Started fetching project team. ProjectId: {ProjectId}, ServiceId: {ServiceId}, OrganizationId: {OrganizationId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}",
|
||||||
|
projectId, serviceId ?? Guid.Empty, organizationId ?? Guid.Empty, tenantId, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Use a single DbContext instance
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
|
||||||
|
// Fetch project and tenant entities in parallel
|
||||||
|
var projectTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await context.Projects.FirstOrDefaultAsync(p => p.Id == projectId && p.TenantId == tenantId);
|
||||||
|
});
|
||||||
|
|
||||||
|
var tenantTask = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await using var context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
return await context.Tenants.FirstOrDefaultAsync(t => t.Id == tenantId);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Task.WhenAll(projectTask, tenantTask);
|
||||||
|
|
||||||
|
var project = await projectTask;
|
||||||
|
var tenant = await tenantTask;
|
||||||
|
|
||||||
|
if (project == null || tenant == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Project {ProjectId} or Tenant {TenantId} not found in the database.", projectId, tenantId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Project or tenant not found", "Project or tenant record not found", 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check permission to view project team
|
||||||
|
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId);
|
||||||
|
if (!hasProjectPermission)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Access denied: User {EmployeeId} tried to get team for Project {ProjectId}", loggedInEmployee.Id, projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Access denied", "User does not have permission to view this project team", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query ProjectOrgMappings for associated organizations
|
||||||
|
var organizationQuery = _context.ProjectOrgMappings
|
||||||
|
.Include(po => po.ProjectService)
|
||||||
|
.Where(po => po.ProjectService != null && po.ProjectService.ProjectId == projectId);
|
||||||
|
|
||||||
|
// Restrict organizations for non-PMC/Promoter users
|
||||||
|
if (loggedInEmployee.OrganizationId != project.PMCId &&
|
||||||
|
loggedInEmployee.OrganizationId != project.PromoterId &&
|
||||||
|
loggedInEmployee.OrganizationId != tenant.OrganizationId)
|
||||||
|
{
|
||||||
|
organizationQuery = organizationQuery.Where(po =>
|
||||||
|
po.ParentOrganizationId == loggedInEmployee.OrganizationId ||
|
||||||
|
po.OrganizationId == loggedInEmployee.OrganizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var organizationIds = await organizationQuery.Select(po => po.OrganizationId).Distinct().ToListAsync();
|
||||||
|
|
||||||
|
// Add PMC, Promoter, Tenant organizations for privileged users
|
||||||
|
if (loggedInEmployee.OrganizationId == project.PMCId ||
|
||||||
|
loggedInEmployee.OrganizationId == project.PromoterId ||
|
||||||
|
loggedInEmployee.OrganizationId == tenant.OrganizationId)
|
||||||
|
{
|
||||||
|
organizationIds.Add(project.PMCId);
|
||||||
|
organizationIds.Add(project.PromoterId);
|
||||||
|
organizationIds.Add(tenant.OrganizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
organizationIds = organizationIds.Distinct().ToList();
|
||||||
|
|
||||||
|
// Build ProjectAllocation query for employees by service/organization if specified
|
||||||
|
var allocationQuery = _context.ProjectAllocations
|
||||||
|
.Include(pa => pa.Employee)
|
||||||
|
.ThenInclude(e => e!.JobRole)
|
||||||
|
.Where(pa => pa.ProjectId == projectId
|
||||||
|
&& pa.Employee != null
|
||||||
|
&& organizationIds.Contains(pa.Employee.OrganizationId));
|
||||||
|
|
||||||
|
if (serviceId.HasValue)
|
||||||
|
{
|
||||||
|
allocationQuery = allocationQuery.Where(pa => pa.ServiceId == serviceId);
|
||||||
|
}
|
||||||
|
if (organizationId.HasValue)
|
||||||
|
{
|
||||||
|
allocationQuery = allocationQuery.Where(pa => pa.Employee != null && pa.Employee.OrganizationId == organizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectAllocations = await allocationQuery.ToListAsync();
|
||||||
|
|
||||||
|
// Map to distinct EmployeeVM results
|
||||||
|
var employeeList = projectAllocations
|
||||||
|
.Select(pa => _mapper.Map<EmployeeVM>(pa.Employee))
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
_logger.LogInfo("Fetched {EmployeeCount} employees for Project {ProjectId}.", employeeList.Count, projectId);
|
||||||
|
|
||||||
|
return ApiResponse<object>.SuccessResponse(employeeList, "Employee list fetched successfully", 200);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occurred while fetching project team for ProjectId: {ProjectId}", projectId);
|
||||||
|
return ApiResponse<object>.ErrorResponse("Internal error", "An error occurred while fetching the project team", 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -23,6 +23,7 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
|||||||
Task<ApiResponse<object>> GetProjectsByEmployeeAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetProjectsByEmployeeAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<List<ProjectAllocationVM>>> AssigneProjectsToEmployeeAsync(List<ProjectsAllocationDto> projectAllocationDtos, Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<List<ProjectAllocationVM>>> AssigneProjectsToEmployeeAsync(List<ProjectsAllocationDto> projectAllocationDtos, Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Task<ApiResponse<object>> GetProjectTeamByServiceAndOrganizationAsync(Guid projectId, Guid? serviceId, Guid? organizationId, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
|
||||||
Task<ApiResponse<object>> GetInfraDetailsAsync(Guid projectId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetInfraDetailsAsync(Guid projectId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee);
|
||||||
Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee);
|
Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid? serviceId, Guid tenantId, Employee loggedInEmployee);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user