Getting the employee list of user's organization only
This commit is contained in:
parent
42da1f12cf
commit
fe1dfd7293
@ -19,6 +19,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Data;
|
||||
using System.Net;
|
||||
@ -33,7 +34,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
{
|
||||
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly IServiceScopeFactory _serviceScope;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly EmployeeHelper _employeeHelper;
|
||||
@ -49,7 +50,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
private readonly Guid organizationId;
|
||||
|
||||
|
||||
public EmployeeController(IServiceScopeFactory serviceScope,
|
||||
public EmployeeController(IServiceScopeFactory serviceScopeFactory,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
IEmailSender emailSender,
|
||||
ApplicationDbContext context,
|
||||
@ -63,7 +64,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
IMapper mapper,
|
||||
GeneralHelper generalHelper)
|
||||
{
|
||||
_serviceScope = serviceScope;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
_emailSender = emailSender;
|
||||
@ -119,9 +120,8 @@ namespace MarcoBMS.Services.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("list/{projectid?}")]
|
||||
public async Task<IActionResult> GetEmployeesByProject(Guid? projectid, [FromQuery] bool ShowInactive)
|
||||
[HttpGet("list/{projectId?}")]
|
||||
public async Task<IActionResult> GetEmployeesByProjectAsync(Guid? projectId, [FromQuery] bool showInactive = false)
|
||||
{
|
||||
// Step 1: Validate incoming request model state
|
||||
if (!ModelState.IsValid)
|
||||
@ -135,56 +135,112 @@ namespace MarcoBMS.Services.Controllers
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||
}
|
||||
|
||||
// Step 2: Get logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
_logger.LogInfo("GetEmployeesByProject called by EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, ShowInactive: {ShowInactive}",
|
||||
loggedInEmployee.Id, projectid ?? Guid.Empty, ShowInactive);
|
||||
|
||||
// Step 3: Fetch project access and permissions
|
||||
var projectIds = await _projectServices.GetMyProjectIdsAsync(tenantId, loggedInEmployee);
|
||||
|
||||
var hasViewAllEmployeesPermission = await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
|
||||
var hasViewTeamMembersPermission = await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id);
|
||||
|
||||
List<EmployeeVM> result = new();
|
||||
|
||||
// Step 4: Determine access level and fetch employees accordingly
|
||||
if (hasViewAllEmployeesPermission || projectid != null)
|
||||
List<EmployeeVM> result = new List<EmployeeVM>();
|
||||
try
|
||||
{
|
||||
result = await _employeeHelper.GetEmployeeByProjectId(tenantId, projectid, ShowInactive);
|
||||
_logger.LogInfo("Employee list fetched using full access or specific project.");
|
||||
}
|
||||
else if (hasViewTeamMembersPermission && !ShowInactive)
|
||||
{
|
||||
var employeeIds = await _context.ProjectAllocations
|
||||
.Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive && pa.TenantId == tenantId)
|
||||
.Select(pa => pa.EmployeeId)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
// Dependency injection scope for services
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
var employees = await _context.Employees
|
||||
.Include(fp => fp.JobRole)
|
||||
.Where(e => employeeIds.Contains(e.Id) && e.JobRole != null && e.IsActive && e.TenantId == tenantId)
|
||||
// Step 2: Get logged-in employee details
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
_logger.LogInfo("GetEmployeesByProject called. EmployeeId: {EmployeeId}, ProjectId: {ProjectId}, showInactive: {ShowInactive}",
|
||||
loggedInEmployee.Id, projectId ?? Guid.Empty, showInactive);
|
||||
|
||||
// Step 3: Fetch permissions concurrently
|
||||
var viewAllTask = Task.Run(async () =>
|
||||
{
|
||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
return await _permission.HasPermission(PermissionsMaster.ViewAllEmployees, loggedInEmployee.Id);
|
||||
});
|
||||
var viewTeamTask = Task.Run(async () =>
|
||||
{
|
||||
var _permission = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
return await _permission.HasPermission(PermissionsMaster.ViewTeamMembers, loggedInEmployee.Id);
|
||||
});
|
||||
|
||||
await Task.WhenAll(viewAllTask, viewTeamTask);
|
||||
|
||||
var hasViewAllEmployeesPermission = viewAllTask.Result;
|
||||
var hasViewTeamMembersPermission = viewTeamTask.Result;
|
||||
|
||||
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
|
||||
.AsNoTracking() // Optimize EF query for read-only operation[web:1][web:13][web:18]
|
||||
.Include(e => e.JobRole)
|
||||
.Where(e => e.OrganizationId == organizationId);
|
||||
|
||||
employeeQuery = showInactive
|
||||
? employeeQuery.Where(e => !e.IsActive)
|
||||
: employeeQuery.Where(e => e.IsActive);
|
||||
|
||||
employees = await employeeQuery.ToListAsync();
|
||||
_logger.LogInfo("Employee list fetched with full access. Count: {Count}", employees.Count);
|
||||
}
|
||||
else if (hasViewTeamMembersPermission && !showInactive && !projectId.HasValue)
|
||||
{
|
||||
// Only active team members with limited permission
|
||||
var projectIds = await _projectServices.GetMyProjectIdsAsync(tenantId, loggedInEmployee);
|
||||
|
||||
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!)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
result = employees.Select(e => e.ToEmployeeVMFromEmployee()).ToList();
|
||||
_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();
|
||||
|
||||
_logger.LogInfo("Employees successfully fetched. EmployeeId: {EmployeeId} for ProjectId: {ProjectId}. Final Count: {Count}",
|
||||
loggedInEmployee.Id, projectId ?? Guid.Empty, result.Count);
|
||||
|
||||
_logger.LogInfo("Employee list fetched using limited access (active only).");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Access denied for EmployeeId: {EmployeeId} - insufficient permissions.", loggedInEmployee.Id);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
|
||||
}
|
||||
|
||||
// Step 5: Log and return results
|
||||
_logger.LogInfo("Employees fetched successfully by EmployeeId: {EmployeeId} for ProjectId: {ProjectId}. Count: {Count}",
|
||||
loggedInEmployee.Id, projectid ?? Guid.Empty, result.Count);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 6: Error logging and response[web:6]
|
||||
_logger.LogError(ex, "Exception occurred while getting the list of employees");
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal server error. Please try again later.", null, 500));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("basic")]
|
||||
public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString)
|
||||
{
|
||||
@ -857,7 +913,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> SuspendEmployee(Guid id, [FromQuery] bool active = false)
|
||||
{
|
||||
using var scope = _serviceScope.CreateScope();
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
|
||||
Guid tenantId = _userHelper.GetTenantId();
|
||||
var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
@ -357,6 +357,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
SPRID = organization.SPRID,
|
||||
AssignedDate = DateTime.UtcNow,
|
||||
IsActive = true,
|
||||
AssignedById = loggedInEmployee.Id,
|
||||
TenantId = project.TenantId
|
||||
};
|
||||
_context.TenantOrgMappings.Add(newServiceProviderTenantMapping);
|
||||
@ -365,20 +366,21 @@ namespace Marco.Pms.Services.Controllers
|
||||
List<ProjectOrgMapping> projectOrgMappings = new List<ProjectOrgMapping>();
|
||||
List<ProjectServiceMapping> projectServiceMappings = new List<ProjectServiceMapping>();
|
||||
|
||||
if (isPMC && model.OrganizationTypeId != ServiceProvider && model.OrganizationTypeId != SubContractorProvider)
|
||||
{
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to assign this type of organization", 403));
|
||||
}
|
||||
if (isServiceProvider && model.OrganizationTypeId == ServiceProvider)
|
||||
{
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "You don't have access to assign this type of organization", 403));
|
||||
}
|
||||
|
||||
foreach (var serviceId in model.ServiceIds)
|
||||
{
|
||||
if (isPMC && model.OrganizationTypeId != ServiceProvider && model.OrganizationTypeId != SubContractorProvider)
|
||||
var service = await _context.ServiceMasters.FirstOrDefaultAsync(s => s.Id == serviceId);
|
||||
if (service == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (isServiceProvider && model.OrganizationTypeId == ServiceProvider)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var isServiceExist = await _context.ServiceMasters.AnyAsync(s => s.Id == serviceId);
|
||||
if (!isServiceExist)
|
||||
{
|
||||
continue;
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Service not found", "Service not found in database", 404));
|
||||
}
|
||||
var projectService = projectServices.FirstOrDefault(ps => ps.ServiceId == serviceId);
|
||||
if (projectService == null)
|
||||
@ -403,14 +405,17 @@ namespace Marco.Pms.Services.Controllers
|
||||
OrganizationTypeId = model.OrganizationTypeId,
|
||||
ParentOrganizationId = model.ParentOrganizationId ?? loggedInEmployee.OrganizationId,
|
||||
AssignedDate = DateTime.UtcNow,
|
||||
AssignedById = loggedInEmployee.Id,
|
||||
TenantId = project.TenantId
|
||||
};
|
||||
var projectOrganization = projectOrganizations
|
||||
.FirstOrDefault(po => po.ProjectService != null && po.ProjectService.ProjectId == project.Id && po.ProjectService.ServiceId == serviceId);
|
||||
if (projectOrganization == null)
|
||||
.FirstOrDefault(po => po.ProjectService != null && po.ProjectService.ProjectId == project.Id && po.ProjectService.ServiceId == serviceId
|
||||
&& po.OrganizationId == model.OrganizationId);
|
||||
if (projectOrganization != null)
|
||||
{
|
||||
projectOrgMappings.Add(projectOrgMapping);
|
||||
return StatusCode(409, ApiResponse<object>.ErrorResponse("Organization is already assigned to this project", "Organization is already assigned to this project", 409));
|
||||
}
|
||||
projectOrgMappings.Add(projectOrgMapping);
|
||||
}
|
||||
|
||||
if (projectServiceMappings.Any())
|
||||
@ -495,6 +500,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
SPRID = organization.SPRID,
|
||||
AssignedDate = DateTime.UtcNow,
|
||||
IsActive = true,
|
||||
AssignedById = loggedInEmployee.Id,
|
||||
TenantId = tenantId
|
||||
};
|
||||
_context.TenantOrgMappings.Add(newServiceProviderTenantMapping);
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
using AutoMapper;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Mapper;
|
||||
@ -13,10 +14,12 @@ namespace MarcoBMS.Services.Helpers
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly ILoggingService _logger;
|
||||
public EmployeeHelper(ApplicationDbContext context, ILoggingService logger)
|
||||
private readonly IMapper _mapper;
|
||||
public EmployeeHelper(ApplicationDbContext context, ILoggingService logger, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
}
|
||||
public async Task<Employee> GetEmployeeByID(Guid EmployeeID)
|
||||
{
|
||||
@ -72,38 +75,36 @@ namespace MarcoBMS.Services.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<EmployeeVM>> GetEmployeeByProjectId(Guid tenantId, Guid? projectId, bool ShowInActive)
|
||||
public async Task<List<EmployeeVM>> GetEmployeeByProjectId(Guid organizationId, Guid tenantId, Guid? projectId, bool ShowInActive)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<EmployeeVM> result = new List<EmployeeVM>();
|
||||
List<Employee> employees = new List<Employee>();
|
||||
if (projectId.HasValue)
|
||||
{
|
||||
var employeeIds = await _context.ProjectAllocations
|
||||
.Where(pa => projectId == pa.ProjectId && pa.IsActive && pa.TenantId == tenantId)
|
||||
.Select(pa => pa.EmployeeId)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
var employees = await _context.Employees
|
||||
.Include(fp => fp.JobRole)
|
||||
.Where(e => employeeIds.Contains(e.Id) && e.JobRole != null && e.IsActive && e.TenantId == tenantId)
|
||||
employees = await _context.ProjectAllocations
|
||||
.Include(pa => pa.Employee)
|
||||
.ThenInclude(e => e!.JobRole)
|
||||
.Where(pa => projectId == pa.ProjectId && pa.IsActive && pa.TenantId == tenantId && pa.Employee != null && pa.Employee.IsActive)
|
||||
.Select(pa => pa.Employee!)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
result = employees.Select(e => e.ToEmployeeVMFromEmployee()).ToList();
|
||||
|
||||
}
|
||||
else if (ShowInActive)
|
||||
{
|
||||
result = await _context.Employees.Where(c => c.TenantId == tenantId && c.IsActive == false).Include(fp => fp.JobRole)
|
||||
.Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync();
|
||||
employees = await _context.Employees
|
||||
.Include(fp => fp.JobRole)
|
||||
.Where(c => c.OrganizationId == organizationId && c.IsActive == false)
|
||||
.ToListAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await _context.Employees.Where(c => c.TenantId == tenantId && c.IsActive == true).Include(fp => fp.JobRole)
|
||||
.Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync();
|
||||
employees = await _context.Employees
|
||||
.Include(fp => fp.JobRole)
|
||||
.Where(c => c.OrganizationId == organizationId && c.IsActive == true)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
var result = employees.Select(e => _mapper.Map<EmployeeVM>(e)).Distinct().ToList();
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
Loading…
x
Reference in New Issue
Block a user