sozsoft-platform/api/src/Sozsoft.Platform.Application/OrgChart/OrgChartAppService.cs

133 lines
4.8 KiB
C#
Raw Normal View History

using System;
2026-05-04 19:50:21 +00:00
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Extensions;
2026-05-04 19:50:21 +00:00
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);
2026-07-11 20:35:32 +00:00
var positionsByDepartment = jobPositions
.GroupBy(position => position.DepartmentId)
.ToDictionary(group => group.Key, group => group.OrderBy(position => position.Name).ToList());
var usersByJobPosition = GroupUsersByJobPosition(users);
2026-05-04 19:50:21 +00:00
var topPositionByDepartment = new Dictionary<Guid, JobPosition>();
foreach (var department in departments)
{
2026-07-11 20:35:32 +00:00
if (!positionsByDepartment.TryGetValue(department.Id, out var departmentPositions))
2026-05-04 19:50:21 +00:00
{
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 =>
2026-05-04 19:50:21 +00:00
{
topPositionByDepartment.TryGetValue(d.Id, out var topPosition);
return new OrgChartNodeDto
{
Id = d.Id,
Name = d.Name,
ParentId = d.ParentId,
JobPositionId = topPosition?.Id,
JobPositionName = topPosition?.Name,
2026-07-11 20:35:32 +00:00
Users = topPosition != null && usersByJobPosition.TryGetValue(topPosition.Id, out var positionUsers)
? positionUsers
: [],
};
2026-05-04 19:50:21 +00:00
}).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);
2026-07-11 20:35:32 +00:00
var usersByJobPosition = GroupUsersByJobPosition(users);
2026-05-04 19:50:21 +00:00
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,
JobPositionId = jp.Id,
JobPositionName = jp.Name,
2026-07-11 20:35:32 +00:00
Users = usersByJobPosition.TryGetValue(jp.Id, out var positionUsers)
? positionUsers
: [],
2026-05-04 19:50:21 +00:00
}).ToList();
return nodes;
}
2026-07-11 20:35:32 +00:00
private static Dictionary<Guid, List<OrgChartUserDto>> GroupUsersByJobPosition(
IEnumerable<IdentityUser> users)
{
return users
.GroupBy(user => user.GetJobPositionId())
.ToDictionary(
group => group.Key,
group => group.Select(user => new OrgChartUserDto
{
Id = user.Id,
FullName = user.GetFullName(),
Email = user.Email,
UserName = user.UserName,
PhoneNumber = user.PhoneNumber
}).ToList());
}
2026-05-04 19:50:21 +00:00
}