using LCU.API.Internal.Operations.IncentiveApi.Exceptions; using LCU.API.Internal.Operations.IncentiveApi.Models; using LCU.API.Internal.Operations.IncentiveApiLib.Repositories; using LCU.Library.Internal.IncentiveApiModels.Entities; using LCU.Library.Internal.IncentiveApiModels.Enums; using LCU.Library.Internal.IncentiveApiModels.Common; namespace LCU.API.Internal.Operations.IncentiveApi.Services; public class DepartmentService : IDepartmentService { private readonly IDepartmentRepository _departmentRepository; private readonly IUnitOfWork _unitOfWork; private readonly IUserAssignmentService _userAssignmentService; public DepartmentService(IDepartmentRepository departmentRepository, IUserAssignmentService userAssignmentService, IUnitOfWork unitOfWork) { _departmentRepository = departmentRepository; _userAssignmentService = userAssignmentService; _unitOfWork = unitOfWork; } public async Task> GetAllDepartmentsAsync() { try { return await _departmentRepository.GetAllDepartmentsAsync(); } catch (Exception ex) { Log.Error(ex, "Failed to Retrieve All Departments"); throw new ServerErrorException(); } } public async Task GetDepartmentByIdAsync(int id) { try { var department = await _departmentRepository.FindDepartmentByIdAsync(id); if (department == null) { throw new NotFoundException($"Could Not Find Department With Id {id}"); } return department; } catch (NotFoundException) { throw; } catch (Exception ex) { Log.Error(ex, $"Failed to Retrieve Department with Id {id}"); throw new ServerErrorException(); } } public async Task> GetDepartmentsByRegionAsync(Region region) { try { var departments = await _departmentRepository.FindDepartmentsByRegionAsync(region); if (departments == null) { throw new NotFoundException($"Could Not Find Departments for {region.Name}"); } return departments; } catch (NotFoundException) { throw; } catch (Exception ex) { Log.Error(ex, $"Could Not Find Departments for {region.Name}"); throw new ServerErrorException(); } } public async Task> GetDepartmentsByBusinessLineAsync(BusinessLine businessLine) { var departments = await _departmentRepository.FindDepartmentsByBusinessLineAsync(businessLine); if (departments == null) { throw new NotFoundException($"Could Not Find Departments for {businessLine.Name}"); } return departments; } public async Task> FindDepartmentAssignmentsForRange(int departmentId, MonthRange monthRange) { return await _departmentRepository.FindDepartmentAssignmentsForRange(departmentId, monthRange); } public async Task GetDepartmentsByDayforceGlCodeAsync(int glCode) { var department = await _departmentRepository.GetDepartmentByDayforceGlCode(glCode); if (department == null) { throw new NotFoundException($"Could Not Find Department for {glCode}"); } return department; } public async Task> GetHierarchicalDepartmentsForEmployeeAsync(AppUser employee, bool includeManagers) { try { if (employee.Departments.Any(x => x.Role == Role.Admin)) { return await GetAllDepartmentsAsync(); } var userDept = employee.Departments.FirstOrDefault(x => x.Role == Role.RegionalManager); if (userDept != null && userDept.Department != null && !string.IsNullOrWhiteSpace(userDept.Department.RegionCode)) { var region = Region.FindByCode(userDept.Department.RegionCode); if (region != null) { return await _departmentRepository.FindDepartmentsByRegionAsync(region); } } var includedRoles = Role.LeadershipRoles; if (includeManagers) { includedRoles = Role.DepartmentManagerRoles; } return employee.Departments .Where(x => includedRoles.Contains(x.Role)) .Select(x => x.Department).ToList(); } catch (Exception ex) { Log.Error(ex, "Failed to Retrieve departments user can manage"); throw new ServerErrorException(); } } public async Task UpdateDepartmentAsync(Department department, int id) { try { if (!await IsDepartmentNameUnique(department.DepartmentName, id)) { Log.Debug("Attempted to add department with name that already exists."); throw new DuplicateDataException("DepartmentName"); } var existingDepartment = await _departmentRepository.FindDepartmentByIdAsync(id); if (existingDepartment == null) { throw new NotFoundException($"Could Not Find Department With Id {id}"); } existingDepartment.DepartmentName = department.DepartmentName; existingDepartment.State = department.State; existingDepartment.BusinessLineCode = department.BusinessLineCode; existingDepartment.RegionCode = department.RegionCode; await _unitOfWork.CompleteAsync(); return existingDepartment; } catch (DuplicateDataException) { throw; } catch (Exception ex) { Log.Error(ex, $"Failed to Update Department with Id {id}"); throw new ServerErrorException(); } } public async Task SaveDepartmentAsync(Department newDepartment) { try { if (!await IsDepartmentNameUnique(newDepartment.DepartmentName)) { Log.Debug("Attempted to add department with name that already exists."); throw new DuplicateDataException("DepartmentName"); } var department = await _departmentRepository.SaveDepartmentAsync(newDepartment); await _unitOfWork.CompleteAsync(); return department; } catch (DuplicateDataException) { throw; } catch (Exception ex) { Log.Error(ex, $"Failed to save new Department with Name {newDepartment.DepartmentName}."); throw new ServerErrorException(); } } public async Task IsDepartmentNameUnique(string departmentName, int? id = null) { var existingDepartments = await _departmentRepository.GetAllDepartmentsAsync(); if (!existingDepartments.Any()) { return true; } return !existingDepartments.Where(x => x.Id != id).Any(dept => string.Equals(dept.DepartmentName, departmentName, StringComparison.InvariantCultureIgnoreCase)); } public async Task GetDepartmentDetailsAsync(int id) { var department = await _departmentRepository.FindDepartmentByIdAsync(id); if (department == null) { throw new NotFoundException($"Could Not Find Department With ID {id}"); } var assignments = await _departmentRepository.FindCurrentDepartmentAssignments(id); var departmentDetails = new DepartmentDetails { Department = department, Assignments = assignments, }; if (department.RegionCode != null) { var regionalManagerAssignment = await _userAssignmentService.GetUserAssignment(AssignmentType.RegionalManager, department.RegionCode); departmentDetails.RegionalManager = regionalManagerAssignment?.AppUser; } return departmentDetails; } }