211 lines
6.7 KiB
C#
211 lines
6.7 KiB
C#
using Microsoft.EntityFrameworkCore;
|
||
using MilitaryTrainingManagement.Data;
|
||
using MilitaryTrainingManagement.Models.Entities;
|
||
using MilitaryTrainingManagement.Models.Enums;
|
||
using MilitaryTrainingManagement.Services.Interfaces;
|
||
|
||
namespace MilitaryTrainingManagement.Services.Implementations;
|
||
|
||
/// <summary>
|
||
/// 组织管理服务实现
|
||
/// </summary>
|
||
public class OrganizationService : IOrganizationService
|
||
{
|
||
private readonly ApplicationDbContext _context;
|
||
|
||
public OrganizationService(ApplicationDbContext context)
|
||
{
|
||
_context = context;
|
||
}
|
||
|
||
public async Task<OrganizationalUnit?> GetByIdAsync(int id)
|
||
{
|
||
return await _context.OrganizationalUnits
|
||
.Include(u => u.Parent)
|
||
.Include(u => u.Children)
|
||
.FirstOrDefaultAsync(u => u.Id == id);
|
||
}
|
||
|
||
public async Task<IEnumerable<OrganizationalUnit>> GetAllAsync()
|
||
{
|
||
var allUnits = await _context.OrganizationalUnits
|
||
.OrderBy(u => u.Level)
|
||
.ThenBy(u => u.CreatedAt) // 按创建时间排序,新的在后面
|
||
.ToListAsync();
|
||
|
||
// 构建树形结构,只返回顶级节点(师团级)
|
||
var rootUnits = allUnits.Where(u => u.ParentId == null).OrderBy(u => u.CreatedAt).ToList();
|
||
|
||
// 递归构建子节点
|
||
foreach (var root in rootUnits)
|
||
{
|
||
BuildChildrenTree(root, allUnits);
|
||
}
|
||
|
||
return rootUnits;
|
||
}
|
||
|
||
private void BuildChildrenTree(OrganizationalUnit parent, List<OrganizationalUnit> allUnits)
|
||
{
|
||
var children = allUnits.Where(u => u.ParentId == parent.Id).OrderBy(u => u.CreatedAt).ToList();
|
||
parent.Children = children;
|
||
|
||
foreach (var child in children)
|
||
{
|
||
child.Parent = parent;
|
||
BuildChildrenTree(child, allUnits);
|
||
}
|
||
}
|
||
|
||
public async Task<IEnumerable<OrganizationalUnit>> GetSubordinatesAsync(int unitId)
|
||
{
|
||
var unit = await _context.OrganizationalUnits.FindAsync(unitId);
|
||
if (unit == null)
|
||
return Enumerable.Empty<OrganizationalUnit>();
|
||
|
||
return await GetAllSubordinatesRecursiveAsync(unitId);
|
||
}
|
||
|
||
private async Task<List<OrganizationalUnit>> GetAllSubordinatesRecursiveAsync(int unitId)
|
||
{
|
||
var result = new List<OrganizationalUnit>();
|
||
var directChildren = await _context.OrganizationalUnits
|
||
.Where(u => u.ParentId == unitId)
|
||
.ToListAsync();
|
||
|
||
foreach (var child in directChildren)
|
||
{
|
||
result.Add(child);
|
||
var grandChildren = await GetAllSubordinatesRecursiveAsync(child.Id);
|
||
result.AddRange(grandChildren);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
public async Task<OrganizationalUnit> CreateAsync(string name, OrganizationalLevel level, int? parentId)
|
||
{
|
||
if (parentId.HasValue)
|
||
{
|
||
var parent = await _context.OrganizationalUnits.FindAsync(parentId.Value);
|
||
if (parent == null)
|
||
throw new ArgumentException("父级组织单位不存在");
|
||
|
||
if ((int)level <= (int)parent.Level)
|
||
throw new ArgumentException("子级组织层级必须低于父级");
|
||
}
|
||
else if (level != OrganizationalLevel.Division)
|
||
{
|
||
throw new ArgumentException("非师团级组织必须有父级单位");
|
||
}
|
||
|
||
var unit = new OrganizationalUnit
|
||
{
|
||
Name = name,
|
||
Level = level,
|
||
ParentId = parentId,
|
||
CreatedAt = DateTime.UtcNow
|
||
};
|
||
|
||
_context.OrganizationalUnits.Add(unit);
|
||
await _context.SaveChangesAsync();
|
||
return unit;
|
||
}
|
||
|
||
public async Task<OrganizationalUnit> UpdateAsync(int id, string name)
|
||
{
|
||
var unit = await _context.OrganizationalUnits.FindAsync(id);
|
||
if (unit == null)
|
||
throw new ArgumentException("组织单位不存在");
|
||
|
||
unit.Name = name;
|
||
await _context.SaveChangesAsync();
|
||
return unit;
|
||
}
|
||
|
||
public async Task DeleteAsync(int id)
|
||
{
|
||
var unit = await _context.OrganizationalUnits
|
||
.Include(u => u.Children)
|
||
.FirstOrDefaultAsync(u => u.Id == id);
|
||
|
||
if (unit == null)
|
||
throw new ArgumentException("组织单位不存在");
|
||
|
||
if (unit.Children.Any())
|
||
throw new InvalidOperationException("无法删除有下级单位的组织");
|
||
|
||
// 检查是否有关联的用户账户
|
||
var hasUsers = await _context.UserAccounts
|
||
.AnyAsync(u => u.OrganizationalUnitId == id);
|
||
if (hasUsers)
|
||
throw new InvalidOperationException("无法删除有关联用户的组织");
|
||
|
||
_context.OrganizationalUnits.Remove(unit);
|
||
await _context.SaveChangesAsync();
|
||
}
|
||
|
||
public async Task<bool> IsSubordinateOfAsync(int unitId, int potentialParentId)
|
||
{
|
||
var unit = await _context.OrganizationalUnits.FindAsync(unitId);
|
||
if (unit == null)
|
||
return false;
|
||
|
||
var currentParentId = unit.ParentId;
|
||
while (currentParentId.HasValue)
|
||
{
|
||
if (currentParentId.Value == potentialParentId)
|
||
return true;
|
||
|
||
var parent = await _context.OrganizationalUnits.FindAsync(currentParentId.Value);
|
||
currentParentId = parent?.ParentId;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public async Task<IEnumerable<int>> GetAllSubordinateIdsAsync(int unitId)
|
||
{
|
||
var subordinates = await GetAllSubordinatesRecursiveAsync(unitId);
|
||
return subordinates.Select(u => u.Id);
|
||
}
|
||
|
||
public async Task<bool> IsUnitOrSubordinateAsync(int userUnitId, int targetUnitId)
|
||
{
|
||
// 如果是同一个单位,直接返回true
|
||
if (userUnitId == targetUnitId)
|
||
return true;
|
||
|
||
// 检查目标单位是否是用户单位的下级
|
||
return await IsSubordinateOfAsync(targetUnitId, userUnitId);
|
||
}
|
||
|
||
public async Task<bool> IsParentUnitAsync(int parentUnitId, int childUnitId)
|
||
{
|
||
var childUnit = await _context.OrganizationalUnits.FindAsync(childUnitId);
|
||
if (childUnit == null)
|
||
return false;
|
||
|
||
// 检查直接父级关系
|
||
if (childUnit.ParentId == parentUnitId)
|
||
return true;
|
||
|
||
// 检查是否是上级单位(递归向上查找)
|
||
return await IsSubordinateOfAsync(childUnitId, parentUnitId);
|
||
}
|
||
|
||
public async Task<IEnumerable<int>> GetAllAncestorIdsAsync(int unitId)
|
||
{
|
||
var result = new List<int>();
|
||
var currentUnit = await _context.OrganizationalUnits.FindAsync(unitId);
|
||
|
||
while (currentUnit?.ParentId != null)
|
||
{
|
||
result.Add(currentUnit.ParentId.Value);
|
||
currentUnit = await _context.OrganizationalUnits.FindAsync(currentUnit.ParentId.Value);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
}
|