using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using MilitaryTrainingManagement.Data;
using MilitaryTrainingManagement.Models.Entities;
using MilitaryTrainingManagement.Models.Enums;
using MilitaryTrainingManagement.Services.Interfaces;
namespace MilitaryTrainingManagement.Services.Implementations;
///
/// 人员管理服务实现
///
public class PersonnelService : IPersonnelService
{
private readonly ApplicationDbContext _context;
private readonly IOrganizationService _organizationService;
private readonly IFileUploadService _fileUploadService;
private readonly IWorkflowService _workflowService;
private readonly ILogger _logger;
public PersonnelService(
ApplicationDbContext context,
IOrganizationService organizationService,
IFileUploadService fileUploadService,
IWorkflowService workflowService,
ILogger logger)
{
_context = context;
_organizationService = organizationService;
_fileUploadService = fileUploadService;
_workflowService = workflowService;
_logger = logger;
}
public async Task GetByIdAsync(int id)
{
return await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.FirstOrDefaultAsync(p => p.Id == id);
}
public async Task> GetByUnitAsync(int unitId, bool includeSubordinates = false)
{
if (includeSubordinates)
{
var subordinates = await _organizationService.GetSubordinatesAsync(unitId);
var unitIds = subordinates.Select(s => s.Id).ToList();
unitIds.Add(unitId);
return await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.Where(p => unitIds.Contains(p.SubmittedByUnitId))
.OrderByDescending(p => p.SubmittedAt)
.ToListAsync();
}
return await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.Where(p => p.SubmittedByUnitId == unitId)
.OrderByDescending(p => p.SubmittedAt)
.ToListAsync();
}
public async Task CreateAsync(Personnel personnel)
{
personnel.Status = PersonnelStatus.Pending;
personnel.SubmittedAt = DateTime.UtcNow;
_context.Personnel.Add(personnel);
await _context.SaveChangesAsync();
return personnel;
}
public async Task UpdateAsync(Personnel personnel)
{
_context.Personnel.Update(personnel);
await _context.SaveChangesAsync();
return personnel;
}
public async Task ApproveAsync(int personnelId, int approvedByUnitId, PersonnelLevel level)
{
var personnel = await _context.Personnel.FindAsync(personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId);
if (approvedByUnit == null)
throw new ArgumentException("审批单位不存在");
// 验证审批单位层级必须高于或等于人员等级(数值越小层级越高)
var unitLevelValue = (int)approvedByUnit.Level;
var personnelLevelValue = (int)level;
if (unitLevelValue > personnelLevelValue)
throw new ArgumentException("审批单位层级不足以审批该等级人才");
var previousStatus = personnel.Status;
var previousLevel = personnel.ApprovedLevel;
personnel.Status = PersonnelStatus.Approved;
personnel.ApprovedByUnitId = approvedByUnitId;
personnel.ApprovedLevel = level;
personnel.ApprovedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
// 记录审批历史
var userId = await GetUserIdByUnitAsync(approvedByUnitId);
await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Approved,
previousStatus, PersonnelStatus.Approved, previousLevel, level,
userId, approvedByUnitId, "审批通过");
_logger.LogInformation("人员 {PersonnelId} 已被单位 {UnitId} 审批通过,等级:{Level}",
personnelId, approvedByUnitId, level);
return personnel;
}
public async Task RejectAsync(int personnelId, int reviewedByUserId)
{
var personnel = await _context.Personnel.FindAsync(personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
var previousStatus = personnel.Status;
personnel.Status = PersonnelStatus.Rejected;
await _context.SaveChangesAsync();
// 记录审批历史
await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Rejected,
previousStatus, PersonnelStatus.Rejected, null, null,
reviewedByUserId, null, "审批拒绝");
_logger.LogInformation("人员 {PersonnelId} 已被用户 {UserId} 拒绝", personnelId, reviewedByUserId);
return personnel;
}
public async Task DeleteAsync(int id)
{
var personnel = await _context.Personnel.FindAsync(id);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
// 删除关联的文件
if (!string.IsNullOrEmpty(personnel.PhotoPath))
{
await _fileUploadService.DeleteFileAsync(personnel.PhotoPath);
}
if (!string.IsNullOrEmpty(personnel.SupportingDocuments))
{
await _fileUploadService.DeleteFileAsync(personnel.SupportingDocuments);
}
_context.Personnel.Remove(personnel);
await _context.SaveChangesAsync();
_logger.LogInformation("人员记录 {PersonnelId} 已删除", id);
}
public async Task SubmitPersonnelAsync(Personnel personnel, IFormFile? photo, IFormFile? supportingDocument)
{
// 验证人员数据完整性
var validation = await ValidatePersonnelDataAsync(personnel);
if (!validation.IsValid)
{
throw new ArgumentException($"人员数据验证失败:{string.Join(", ", validation.Errors)}");
}
// 处理照片上传
if (photo != null)
{
try
{
personnel.PhotoPath = await _fileUploadService.UploadPhotoAsync(photo);
_logger.LogInformation("人员照片上传成功:{PhotoPath}", personnel.PhotoPath);
}
catch (Exception ex)
{
_logger.LogError(ex, "人员照片上传失败");
throw new InvalidOperationException($"照片上传失败:{ex.Message}");
}
}
// 处理支持文档上传
if (supportingDocument != null)
{
try
{
personnel.SupportingDocuments = await _fileUploadService.UploadDocumentAsync(supportingDocument);
_logger.LogInformation("支持文档上传成功:{DocumentPath}", personnel.SupportingDocuments);
}
catch (Exception ex)
{
_logger.LogError(ex, "支持文档上传失败");
throw new InvalidOperationException($"支持文档上传失败:{ex.Message}");
}
}
// 设置提交状态和时间
personnel.Status = PersonnelStatus.Pending;
personnel.SubmittedAt = DateTime.UtcNow;
_context.Personnel.Add(personnel);
await _context.SaveChangesAsync();
_logger.LogInformation("人员数据提交成功,ID:{PersonnelId},提交单位:{UnitId}",
personnel.Id, personnel.SubmittedByUnitId);
return personnel;
}
public async Task ValidatePersonnelDataAsync(Personnel personnel)
{
var errors = new List();
// 验证必填字段
if (string.IsNullOrWhiteSpace(personnel.Name))
errors.Add("姓名不能为空");
if (string.IsNullOrWhiteSpace(personnel.Position))
errors.Add("职位不能为空");
if (string.IsNullOrWhiteSpace(personnel.Rank))
errors.Add("军衔不能为空");
if (string.IsNullOrWhiteSpace(personnel.Gender))
errors.Add("性别不能为空");
if (string.IsNullOrWhiteSpace(personnel.IdNumber))
errors.Add("身份证号不能为空");
if (personnel.Age <= 0 || personnel.Age > 100)
errors.Add("年龄必须在1-100之间");
if (personnel.SubmittedByUnitId <= 0)
errors.Add("提交单位不能为空");
// 验证身份证号格式(简单验证)
if (!string.IsNullOrWhiteSpace(personnel.IdNumber))
{
if (personnel.IdNumber.Length != 18)
errors.Add("身份证号必须为18位");
}
// 验证身份证号唯一性
if (!string.IsNullOrWhiteSpace(personnel.IdNumber))
{
var existingPersonnel = await _context.Personnel
.FirstOrDefaultAsync(p => p.IdNumber == personnel.IdNumber && p.Id != personnel.Id);
if (existingPersonnel != null)
errors.Add("身份证号已存在");
}
// 验证提交单位是否存在
if (personnel.SubmittedByUnitId > 0)
{
var unit = await _context.OrganizationalUnits.FindAsync(personnel.SubmittedByUnitId);
if (unit == null)
errors.Add("提交单位不存在");
}
return errors.Any() ? PersonnelValidationResult.Failure(errors.ToArray()) : PersonnelValidationResult.Success();
}
public async Task GetApprovalTargetUnitAsync(int submittingUnitId)
{
var submittingUnit = await _context.OrganizationalUnits
.Include(u => u.Parent)
.FirstOrDefaultAsync(u => u.Id == submittingUnitId);
if (submittingUnit == null)
throw new ArgumentException("提交单位不存在");
// 审批路由逻辑:提交给上级单位审批
if (submittingUnit.Parent != null)
{
return submittingUnit.Parent;
}
// 如果是师团级别,则自己审批
if (submittingUnit.Level == OrganizationalLevel.Division)
{
return submittingUnit;
}
throw new InvalidOperationException("无法确定审批目标单位");
}
public async Task CanModifyPersonnelAsync(int personnelId)
{
var personnel = await _context.Personnel.FindAsync(personnelId);
if (personnel == null)
return false;
// 只有待审批状态的人员可以直接修改
if (personnel.Status == PersonnelStatus.Pending)
return true;
// 已审批的人员需要通过工作流修改
return false;
}
public async Task RequestPersonnelModificationAsync(int personnelId, int requestedByUserId, string reason, Personnel modifiedPersonnel)
{
var originalPersonnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (originalPersonnel == null)
throw new ArgumentException("人员记录不存在");
if (originalPersonnel.Status != PersonnelStatus.Approved)
throw new InvalidOperationException("只能修改已审批的人员记录");
var user = await _context.UserAccounts
.Include(u => u.OrganizationalUnit)
.FirstOrDefaultAsync(u => u.Id == requestedByUserId);
if (user == null)
throw new ArgumentException("请求用户不存在");
// 序列化原始数据和修改数据
var originalData = JsonSerializer.Serialize(new
{
originalPersonnel.Name,
originalPersonnel.Position,
originalPersonnel.Rank,
originalPersonnel.Gender,
originalPersonnel.IdNumber,
originalPersonnel.ProfessionalTitle,
originalPersonnel.EducationLevel,
originalPersonnel.Age,
originalPersonnel.Height,
originalPersonnel.ContactInfo,
originalPersonnel.Hometown,
originalPersonnel.TrainingParticipation,
originalPersonnel.Achievements
});
var requestedChanges = JsonSerializer.Serialize(new
{
modifiedPersonnel.Name,
modifiedPersonnel.Position,
modifiedPersonnel.Rank,
modifiedPersonnel.Gender,
modifiedPersonnel.IdNumber,
modifiedPersonnel.ProfessionalTitle,
modifiedPersonnel.EducationLevel,
modifiedPersonnel.Age,
modifiedPersonnel.Height,
modifiedPersonnel.ContactInfo,
modifiedPersonnel.Hometown,
modifiedPersonnel.TrainingParticipation,
modifiedPersonnel.Achievements
});
var request = await _workflowService.CreateModificationRequestAsync(
ApprovalRequestType.PersonnelModification,
personnelId,
requestedByUserId,
user.OrganizationalUnitId,
reason,
originalData,
requestedChanges);
_logger.LogInformation("人员修改请求已创建,ID:{RequestId},人员ID:{PersonnelId}",
request.Id, personnelId);
return request;
}
public async Task> GetVisiblePersonnelAsync(int unitId, OrganizationalLevel userLevel)
{
// 根据组织层级获取可见的人员
// 用户只能查看当前和下级组织单位的人员
var subordinates = await _organizationService.GetSubordinatesAsync(unitId);
var visibleUnitIds = subordinates.Select(s => s.Id).ToList();
visibleUnitIds.Add(unitId);
var query = _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.Where(p => visibleUnitIds.Contains(p.SubmittedByUnitId));
// 根据人员等级进一步过滤
// 用户只能查看等级不高于自己组织层级的人员
var maxPersonnelLevel = (PersonnelLevel)(int)userLevel;
query = query.Where(p => p.ApprovedLevel == null || p.ApprovedLevel >= maxPersonnelLevel);
return await query.OrderByDescending(p => p.SubmittedAt).ToListAsync();
}
public async Task TransferPersonnelAsync(int personnelId, int targetUnitId, int approvedByUnitId)
{
var personnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
if (personnel.Status != PersonnelStatus.Approved)
throw new InvalidOperationException("只能转移已审批的人员");
var targetUnit = await _context.OrganizationalUnits.FindAsync(targetUnitId);
if (targetUnit == null)
throw new ArgumentException("目标单位不存在");
var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId);
if (approvedByUnit == null)
throw new ArgumentException("审批单位不存在");
// 验证审批单位有权限进行跨层级转移
// 审批单位层级必须高于或等于目标单位层级
if ((int)approvedByUnit.Level > (int)targetUnit.Level)
throw new UnauthorizedAccessException("审批单位层级不足以进行此转移");
// 更新人员所属单位
personnel.SubmittedByUnitId = targetUnitId;
// 根据新的审批单位重新设置人员等级
var newLevel = (PersonnelLevel)(int)approvedByUnit.Level;
personnel.ApprovedLevel = newLevel;
personnel.ApprovedByUnitId = approvedByUnitId;
personnel.ApprovedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
_logger.LogInformation("人员 {PersonnelId} 已从单位 {FromUnitId} 转移到单位 {ToUnitId},审批单位:{ApprovedByUnitId}",
personnelId, personnel.SubmittedByUnit.Id, targetUnitId, approvedByUnitId);
return personnel;
}
public async Task> GetPendingApprovalPersonnelAsync(int unitId)
{
// 获取需要当前单位审批的人员(来自下级单位的提交)
var subordinates = await _organizationService.GetSubordinatesAsync(unitId);
var subordinateIds = subordinates.Select(s => s.Id).ToList();
return await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Where(p => subordinateIds.Contains(p.SubmittedByUnitId) && p.Status == PersonnelStatus.Pending)
.OrderBy(p => p.SubmittedAt)
.ToListAsync();
}
public async Task> BatchApprovePersonnelAsync(int[] personnelIds, int approvedByUnitId, PersonnelLevel level)
{
var approvedPersonnel = new List();
foreach (var personnelId in personnelIds)
{
try
{
var personnel = await ApproveAsync(personnelId, approvedByUnitId, level);
approvedPersonnel.Add(personnel);
// 记录审批历史
await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Approved,
PersonnelStatus.Pending, PersonnelStatus.Approved, null, level,
await GetUserIdByUnitAsync(approvedByUnitId), approvedByUnitId, "批量审批通过");
}
catch (Exception ex)
{
_logger.LogError(ex, "批量审批人员 {PersonnelId} 失败", personnelId);
// 继续处理其他人员,不中断整个批量操作
}
}
return approvedPersonnel;
}
public async Task> BatchRejectPersonnelAsync(int[] personnelIds, int reviewedByUserId, string reason)
{
var rejectedPersonnel = new List();
foreach (var personnelId in personnelIds)
{
try
{
var personnel = await RejectAsync(personnelId, reviewedByUserId);
rejectedPersonnel.Add(personnel);
// 记录审批历史
await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.Rejected,
PersonnelStatus.Pending, PersonnelStatus.Rejected, null, null,
reviewedByUserId, null, reason);
}
catch (Exception ex)
{
_logger.LogError(ex, "批量拒绝人员 {PersonnelId} 失败", personnelId);
// 继续处理其他人员,不中断整个批量操作
}
}
return rejectedPersonnel;
}
public async Task> GetPersonnelApprovalHistoryAsync(int personnelId)
{
return await _context.PersonnelApprovalHistories
.Include(h => h.ReviewedByUser)
.Include(h => h.ReviewedByUnit)
.Where(h => h.PersonnelId == personnelId)
.OrderByDescending(h => h.ReviewedAt)
.ToListAsync();
}
public async Task CanApprovePersonnelAsync(int userId, int personnelId)
{
var user = await _context.UserAccounts
.Include(u => u.OrganizationalUnit)
.FirstOrDefaultAsync(u => u.Id == userId);
if (user == null)
return false;
var personnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null || personnel.Status != PersonnelStatus.Pending)
return false;
// 同一单位可以审批自己提交的人员
if (user.OrganizationalUnitId == personnel.SubmittedByUnitId)
return true;
// 检查用户的组织单位是否是提交单位的上级
var isParent = await _organizationService.IsParentUnitAsync(user.OrganizationalUnitId, personnel.SubmittedByUnitId);
return isParent;
}
///
/// 记录人员审批历史
///
private async Task RecordApprovalHistoryAsync(int personnelId, PersonnelApprovalAction action,
PersonnelStatus? previousStatus, PersonnelStatus newStatus,
PersonnelLevel? previousLevel, PersonnelLevel? newLevel,
int reviewedByUserId, int? reviewedByUnitId, string? comments)
{
var history = new PersonnelApprovalHistory
{
PersonnelId = personnelId,
Action = action,
PreviousStatus = previousStatus,
NewStatus = newStatus,
PreviousLevel = previousLevel,
NewLevel = newLevel,
ReviewedByUserId = reviewedByUserId,
ReviewedByUnitId = reviewedByUnitId,
Comments = comments,
ReviewedAt = DateTime.UtcNow
};
_context.PersonnelApprovalHistories.Add(history);
await _context.SaveChangesAsync();
}
///
/// 根据单位ID获取用户ID(用于审批历史记录)
///
private async Task GetUserIdByUnitAsync(int unitId)
{
var user = await _context.UserAccounts
.FirstOrDefaultAsync(u => u.OrganizationalUnitId == unitId);
return user?.Id ?? 0; // 如果找不到用户,返回0作为系统操作
}
}