using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sozsoft.Platform.Entities; using Sozsoft.Platform.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Volo.Abp.Domain.Repositories; using Volo.Abp.Identity; namespace Sozsoft.Platform.OrgChart; [Authorize] [Route("api/app/org-chart")] public class OrgChartAppService : PlatformAppService { private readonly IRepository _departmentRepository; private readonly IRepository _jobPositionRepository; private readonly IIdentityUserRepository _userRepository; public OrgChartAppService( IRepository departmentRepository, IRepository jobPositionRepository, IIdentityUserRepository userRepository) { _departmentRepository = departmentRepository; _jobPositionRepository = jobPositionRepository; _userRepository = userRepository; } [HttpGet("departments")] public async Task> GetDepartmentsAsync() { var departments = await _departmentRepository.GetListAsync(); var jobPositions = await _jobPositionRepository.GetListAsync(); var users = await _userRepository.GetListAsync(); var jobById = jobPositions.ToDictionary(x => x.Id); var topPositionByDepartment = new Dictionary(); foreach (var department in departments) { var departmentPositions = jobPositions .Where(x => x.DepartmentId == department.Id) .ToList(); if (!departmentPositions.Any()) { continue; } // Top position means: no parent, parent missing, or parent belongs to another department. var topCandidates = departmentPositions .Where(position => !position.ParentId.HasValue || !jobById.ContainsKey(position.ParentId.Value) || jobById[position.ParentId.Value].DepartmentId != department.Id) .OrderBy(position => position.Name) .ToList(); var selectedTop = topCandidates.FirstOrDefault() ?? departmentPositions .OrderBy(position => position.Name) .First(); topPositionByDepartment[department.Id] = selectedTop; } var nodes = departments.Select(d => new OrgChartNodeDto { Id = d.Id, Name = d.Name, ParentId = d.ParentId, Users = users .Where(u => topPositionByDepartment.TryGetValue(d.Id, out var topPosition) && u.GetJobPositionId() == topPosition.Id) .Select(u => new OrgChartUserDto { Id = u.Id, FullName = u.GetFullName(), Email = u.Email, UserName = u.UserName, }) .ToList(), }).ToList(); return nodes; } [HttpGet("job-positions")] public async Task> GetJobPositionsAsync() { var jobPositions = await _jobPositionRepository.GetListAsync(); var departments = await _departmentRepository.GetListAsync(); var users = await _userRepository.GetListAsync(); var deptDict = departments.ToDictionary(d => d.Id, d => d.Name); var nodes = jobPositions.Select(jp => new OrgChartNodeDto { Id = jp.Id, Name = jp.Name, ParentId = jp.ParentId, DepartmentId = jp.DepartmentId, DepartmentName = deptDict.TryGetValue(jp.DepartmentId, out var name) ? name : null, Users = users .Where(u => u.GetJobPositionId() == jp.Id) .Select(u => new OrgChartUserDto { Id = u.Id, FullName = u.GetFullName(), Email = u.Email, UserName = u.UserName, }) .ToList(), }).ToList(); return nodes; } }