diff --git a/Marco.Pms.Services/Controllers/EmployeeController.cs b/Marco.Pms.Services/Controllers/EmployeeController.cs index a73c808..44f82cf 100644 --- a/Marco.Pms.Services/Controllers/EmployeeController.cs +++ b/Marco.Pms.Services/Controllers/EmployeeController.cs @@ -37,12 +37,15 @@ namespace MarcoBMS.Services.Controllers private readonly ILoggingService _logger; private readonly IHubContext _signalR; private readonly PermissionServices _permission; + private readonly ProjectsHelper _projectsHelper; private readonly Guid ViewAllEmployee; private readonly Guid ViewEmployee; + private readonly Guid tenantId; + public EmployeeController(UserManager userManager, IEmailSender emailSender, ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger, - IHubContext signalR, PermissionServices permission) + IHubContext signalR, PermissionServices permission, ProjectsHelper projectsHelper) { _context = context; _userManager = userManager; @@ -55,6 +58,8 @@ namespace MarcoBMS.Services.Controllers _permission = permission; ViewAllEmployee = Guid.Parse("60611762-7f8a-4fb5-b53f-b1139918796b"); ViewEmployee = Guid.Parse("b82d2b7e-0d52-45f3-997b-c008ea460e7f"); + _projectsHelper = projectsHelper; + tenantId = _userHelper.GetTenantId(); } [HttpGet] @@ -108,30 +113,56 @@ namespace MarcoBMS.Services.Controllers .Select(e => e.ErrorMessage) .ToList(); - _logger.LogWarning("Invalid request model in GetEmployeesByProject. Errors: {@Errors}", errors); + _logger.LogWarning("Invalid model state in GetEmployeesByProject. Errors: {@Errors}", errors); return BadRequest(ApiResponse.ErrorResponse("Invalid data", errors, 400)); } - // Step 2: Get currently logged-in employee + // 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: Check permission (if project ID is not provided, user must have global view permission) + // Step 3: Fetch project access and permissions + List projects = await _projectsHelper.GetMyProjects(tenantId, loggedInEmployee); + var projectIds = projects.Select(p => p.Id).ToList(); + var hasViewAllEmployeePermission = await _permission.HasPermission(ViewAllEmployee, loggedInEmployee.Id); - if (projectid == null && !hasViewAllEmployeePermission) + var hasViewEmployeePermission = await _permission.HasPermission(ViewEmployee, loggedInEmployee.Id); + + List result = new(); + + // Step 4: Determine access level and fetch employees accordingly + if (hasViewAllEmployeePermission || projectid != null) { - _logger.LogWarning("Access denied. EmployeeId: {EmployeeId} tried to access employees without project filter", loggedInEmployee.Id); - return StatusCode(403, ApiResponse.ErrorResponse("You don't have access", "You don't have access", 403)); + result = await _employeeHelper.GetEmployeeByProjectId(tenantId, projectid, ShowInactive); + _logger.LogInfo("Employee list fetched using full access or specific project."); + } + else if (hasViewEmployeePermission && !ShowInactive) + { + var employeeIds = await _context.ProjectAllocations + .Where(pa => projectIds.Contains(pa.ProjectId) && pa.IsActive) + .Select(pa => pa.EmployeeId) + .Distinct() + .ToListAsync(); + + result = await _context.Employees + .Include(fp => fp.JobRole) + .Where(e => employeeIds.Contains(e.Id) && e.IsActive) + .Select(e => e.ToEmployeeVMFromEmployee()) + .ToListAsync(); + + _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.SuccessResponse(result, "Filter applied.", 200)); } - // Step 4: Get employee list from helper based on project and visibility flag - var result = await _employeeHelper.GetEmployeeByProjectId(GetTenantId(), projectid, ShowInactive); + // 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); - _logger.LogInfo("Employees fetched successfully for ProjectId: {ProjectId} by EmployeeId: {EmployeeId}. Result Count: {Count}", - projectid ?? Guid.Empty, loggedInEmployee.Id, result.Count()); - - // Step 5: Return success response with employee data return Ok(ApiResponse.SuccessResponse(result, "Filter applied.", 200)); }