diff --git a/Marco.Pms.Services/Controllers/EmployeeController.cs b/Marco.Pms.Services/Controllers/EmployeeController.cs index 3ccbd1f..8b0eba5 100644 --- a/Marco.Pms.Services/Controllers/EmployeeController.cs +++ b/Marco.Pms.Services/Controllers/EmployeeController.cs @@ -1,10 +1,12 @@ using System.Data; using System.Net; using Marco.Pms.DataAccess.Data; +using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Dtos.Employees; using Marco.Pms.Model.Employees; using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Mapper; +using Marco.Pms.Model.Projects; using Marco.Pms.Model.Utilities; using Marco.Pms.Model.ViewModels; using Marco.Pms.Model.ViewModels.Employee; @@ -30,10 +32,10 @@ namespace MarcoBMS.Services.Controllers private readonly EmployeeHelper _employeeHelper; private readonly UserHelper _userHelper; private readonly IConfiguration _configuration; - + private readonly ILoggingService _logger; public EmployeeController(UserManager userManager, IEmailSender emailSender, - ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration) + ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger) { _context = context; _userManager = userManager; @@ -41,6 +43,7 @@ namespace MarcoBMS.Services.Controllers _employeeHelper = employeeHelper; _userHelper = userHelper; _configuration = configuration; + _logger = logger; } [HttpGet] @@ -204,15 +207,15 @@ namespace MarcoBMS.Services.Controllers if (model.Email != null) { // Check if user already exists by email - IdentityUser? existingUser = await _userHelper.GetRegisteredUser(model.Email); - var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id); + IdentityUser existingUser = await _userHelper.GetRegisteredUser(model.Email) ?? new IdentityUser(); + var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id && e.IsActive == true); if (existingUser != null) { /* Identity user Exists - Create/update employee Employee */ // Update Employee record - existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Email == model.Email && e.Id == model.Id); + existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Email == model.Email && e.Id == model.Id && e.IsActive == true); if (existingEmployee != null) { existingEmployee = GetUpdateEmployeeModel(model, existingEmployee, existingUser); @@ -289,7 +292,7 @@ namespace MarcoBMS.Services.Controllers } else { - var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id); + var existingEmployee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == model.Id && e.IsActive == true); if (existingEmployee != null) { existingEmployee = GetUpdateEmployeeModel(model, existingEmployee); @@ -299,22 +302,100 @@ namespace MarcoBMS.Services.Controllers else { // Create Employee record if missing - Employee newEmployee = GetNewEmployeeModel(model, tenantId, null); + Employee newEmployee = GetNewEmployeeModel(model, tenantId, string.Empty); _context.Employees.Add(newEmployee); } - - await _context.SaveChangesAsync(); + try + { + await _context.SaveChangesAsync(); + } + catch (Exception ex) + { + return BadRequest(ex.InnerException?.Message ?? ex.Message); + } responsemessage = "User created successfully."; } return Ok(ApiResponse.SuccessResponse("Success.", responsemessage, 200)); } -#nullable disable + + [HttpDelete("{id}")] + public async Task SuspendEmployee(Guid id) + { + Guid tenantId = _userHelper.GetTenantId(); + Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.TenantId == tenantId); + if (employee != null) + { + var assignedToTasks = await _context.TaskMembers.Where(t => t.EmployeeId == employee.Id).ToListAsync(); + if (assignedToTasks.Count != 0) + { + List taskIds = assignedToTasks.Select(t => t.TaskAllocationId).ToList(); + var tasks = await _context.TaskAllocations.Where(t => taskIds.Contains(t.Id)).ToListAsync(); + + foreach (var assignedToTask in assignedToTasks) + { + var task = tasks.Find(t => t.Id == assignedToTask.TaskAllocationId); + if (task != null && task.CompletedTask == 0) + { + _logger.LogWarning("Employee with ID {EmployeeId} is currently assigned to any incomplete task", employee.Id); + return BadRequest(ApiResponse.ErrorResponse("Employee is currently assigned to any incomplete task", "Employee is currently assigned to any incomplete task", 400)); + } + } + } + var attendance = await _context.Attendes.Where(a => a.EmployeeID == employee.Id && (a.OutTime == null || a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE)).ToListAsync(); + if (attendance.Count != 0) + { + _logger.LogWarning("Employee with ID {EmployeeId} have any pending check-out or regularization requests", employee.Id); + return BadRequest(ApiResponse.ErrorResponse("Employee have any pending check-out or regularization requests", "Employee have any pending check-out or regularization requests", 400)); + } + employee.IsActive = false; + var projectAllocations = await _context.ProjectAllocations.Where(a => a.EmployeeId == employee.Id).ToListAsync(); + if (projectAllocations.Count != 0) + { + List allocations = new List(); + foreach (var projectAllocation in projectAllocations) + { + projectAllocation.ReAllocationDate = DateTime.UtcNow; + projectAllocation.IsActive = false; + allocations.Add(projectAllocation); + } + _logger.LogInfo("Employee with ID {EmployeeId} has been removed from all assigned projects.", employee.Id); + } + var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId); + if (user != null) + { + user.IsActive = false; + _logger.LogInfo("The application user associated with employee ID {EmployeeId} has been suspended.", employee.Id); + + var refreshTokens = await _context.RefreshTokens.AsNoTracking().Where(t => t.UserId == user.Id).ToListAsync(); + if (refreshTokens.Count != 0) + { + _context.RefreshTokens.RemoveRange(refreshTokens); + _logger.LogInfo("Refresh tokens associated with employee ID {EmployeeId} has been removed.", employee.Id); + } + + } + var roleMapping = await _context.EmployeeRoleMappings.AsNoTracking().Where(r => r.EmployeeId == employee.Id).ToListAsync(); + if (roleMapping.Count != 0) + { + _context.EmployeeRoleMappings.RemoveRange(roleMapping); + _logger.LogInfo("Application role mapping associated with employee ID {EmployeeId} has been removed.", employee.Id); + } + await _context.SaveChangesAsync(); + _logger.LogInfo("Employee with ID {EmployeId} Deleted successfully", employee.Id); + } + else + { + _logger.LogError("Employee with ID {EmploueeId} not found in database", id); + } + return Ok(ApiResponse.SuccessResponse(new { }, "Employee Suspended successfully", 200)); + } + private static Employee GetNewEmployeeModel(CreateUserDto model, Guid TenantId, string ApplicationUserId) { var newEmployee = new Employee { - ApplicationUserId = ApplicationUserId, + ApplicationUserId = String.IsNullOrEmpty(ApplicationUserId) ? null : ApplicationUserId, FirstName = model.FirstName, LastName = model.LastName, Email = model.Email, @@ -337,7 +418,7 @@ namespace MarcoBMS.Services.Controllers return newEmployee; } - private static Employee GetUpdateEmployeeModel(CreateUserDto model, Employee existingEmployee, IdentityUser existingIdentityUser = null) + private static Employee GetUpdateEmployeeModel(CreateUserDto model, Employee existingEmployee, IdentityUser? existingIdentityUser = null) { if (existingEmployee.ApplicationUserId == null && existingIdentityUser != null) { diff --git a/Marco.Pms.Services/Helpers/EmployeeHelper.cs b/Marco.Pms.Services/Helpers/EmployeeHelper.cs index 1ef20d6..20f98af 100644 --- a/Marco.Pms.Services/Helpers/EmployeeHelper.cs +++ b/Marco.Pms.Services/Helpers/EmployeeHelper.cs @@ -20,16 +20,16 @@ namespace MarcoBMS.Services.Helpers public async Task GetEmployeeByID(Guid EmployeeID) { - return await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == EmployeeID) ?? new Employee { }; + return await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == EmployeeID && e.IsActive == true) ?? new Employee { }; } public async Task GetEmployeeByApplicationUserID(string ApplicationUserID) { try { - var result = await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID).ToListAsync(); + var result = await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID && c.IsActive == true).ToListAsync(); - return await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID).SingleOrDefaultAsync() ?? new Employee { }; + return await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID && c.IsActive == true).SingleOrDefaultAsync() ?? new Employee { }; } catch (Exception ex) { @@ -47,7 +47,7 @@ namespace MarcoBMS.Services.Helpers { result = await (from pa in _context.ProjectAllocations.Where(c => c.ProjectId == ProjectId) - join em in _context.Employees.Where(c => c.TenantId == TenentId).Include(fp => fp.JobRole) // Include Feature + join em in _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true).Include(fp => fp.JobRole) // Include Feature on pa.EmployeeId equals em.Id where (em.FirstName != null ? em.FirstName.ToLower().Contains(searchString.ToLower()) : false) || (em.LastName != null ? em.LastName.ToLower().Contains(searchString.ToLower()) : false) select em.ToEmployeeVMFromEmployee() @@ -57,7 +57,7 @@ namespace MarcoBMS.Services.Helpers } else { - result = await _context.Employees.Where(c => c.TenantId == TenentId && + result = await _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true && ((c.FirstName != null ? c.FirstName.ToLower().Contains(searchString.ToLower()) : false) || (c.LastName != null ? c.LastName.ToLower().Contains(searchString.ToLower()) : false))).Include(fp => fp.JobRole) .Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync(); } @@ -80,7 +80,7 @@ namespace MarcoBMS.Services.Helpers { result = await (from pa in _context.ProjectAllocations.Where(c => c.ProjectId == ProjectId) - join em in _context.Employees.Where(c => c.TenantId == TenentId).Include(fp => fp.JobRole) // Include Feature + join em in _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true).Include(fp => fp.JobRole) // Include Feature on pa.EmployeeId equals em.Id select em.ToEmployeeVMFromEmployee() ) @@ -89,7 +89,7 @@ namespace MarcoBMS.Services.Helpers } else { - result = await _context.Employees.Where(c => c.TenantId == TenentId).Include(fp => fp.JobRole) + result = await _context.Employees.Where(c => c.TenantId == TenentId && c.IsActive == true).Include(fp => fp.JobRole) .Select(c => c.ToEmployeeVMFromEmployee()).ToListAsync(); } diff --git a/Marco.Pms.Services/Helpers/UserHelper.cs b/Marco.Pms.Services/Helpers/UserHelper.cs index 73590b8..fabc0f3 100644 --- a/Marco.Pms.Services/Helpers/UserHelper.cs +++ b/Marco.Pms.Services/Helpers/UserHelper.cs @@ -39,7 +39,7 @@ namespace MarcoBMS.Services.Helpers { var user = await GetCurrentUserAsync(); if (user == null) return new Employee { }; - var Employee = await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.ApplicationUserId == user.Id); + var Employee = await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.ApplicationUserId == user.Id && e.IsActive); return Employee ?? new Employee { }; }