sozsoft-platform/api/src/Sozsoft.Platform.Application/OrgChart/OrgChartAppService.cs
2026-05-04 22:50:21 +03:00

121 lines
4.1 KiB
C#

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<Department, Guid> _departmentRepository;
private readonly IRepository<JobPosition, Guid> _jobPositionRepository;
private readonly IIdentityUserRepository _userRepository;
public OrgChartAppService(
IRepository<Department, Guid> departmentRepository,
IRepository<JobPosition, Guid> jobPositionRepository,
IIdentityUserRepository userRepository)
{
_departmentRepository = departmentRepository;
_jobPositionRepository = jobPositionRepository;
_userRepository = userRepository;
}
[HttpGet("departments")]
public async Task<List<OrgChartNodeDto>> 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<Guid, JobPosition>();
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<List<OrgChartNodeDto>> 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;
}
}