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 = null)
{
var personnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId);
if (approvedByUnit == null)
throw new ArgumentException("审批单位不存在");
var previousStatus = personnel.Status;
var previousLevel = personnel.ApprovedLevel;
PersonnelLevel actualLevel;
if (level.HasValue)
{
actualLevel = level.Value;
}
else
{
// 区分首次审批和向上申报两种场景
if (previousStatus == PersonnelStatus.Pending)
{
// 首次审批:人员等级根据提交单位的层级确定
// 例如:营级单位提交的人才,团级审批后应为"营级人才"
actualLevel = (PersonnelLevel)(int)personnel.SubmittedByUnit!.Level;
// 验证审批单位层级必须高于提交单位层级(数值越小层级越高)
var unitLevelValue = (int)approvedByUnit.Level;
var submittedUnitLevelValue = (int)personnel.SubmittedByUnit!.Level;
if (unitLevelValue >= submittedUnitLevelValue)
throw new ArgumentException("审批单位层级必须高于提交单位层级");
}
else if (previousStatus == PersonnelStatus.Approved)
{
// 向上申报:人员等级升级为上报单位(即之前的审批单位)的层级
// 例如:营级人才由团级向上申报,师级审批后应为"团级人才"
if (personnel.ApprovedByUnit == null)
throw new ArgumentException("无法确定上报单位");
actualLevel = (PersonnelLevel)(int)personnel.ApprovedByUnit.Level;
// 验证审批单位层级必须高于当前审批单位层级(数值越小层级越高)
var unitLevelValue = (int)approvedByUnit.Level;
var currentApprovedUnitLevelValue = (int)personnel.ApprovedByUnit.Level;
if (unitLevelValue >= currentApprovedUnitLevelValue)
throw new ArgumentException("审批单位层级必须高于当前审批单位层级");
}
else
{
throw new ArgumentException("该人员状态不允许审批");
}
}
personnel.Status = PersonnelStatus.Approved;
personnel.ApprovedByUnitId = approvedByUnitId;
personnel.ApprovedLevel = actualLevel;
personnel.ApprovedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
// 记录审批历史
var userId = await GetUserIdByUnitAsync(approvedByUnitId);
var actionType = previousStatus == PersonnelStatus.Approved
? PersonnelApprovalAction.LevelUpgraded
: PersonnelApprovalAction.Approved;
var comments = previousStatus == PersonnelStatus.Approved
? $"向上申报通过,等级从{GetLevelName(previousLevel)}升级为{GetLevelName(actualLevel)}"
: "审批通过";
await RecordApprovalHistoryAsync(personnelId, actionType,
previousStatus, PersonnelStatus.Approved, previousLevel, actualLevel,
userId, approvedByUnitId, comments);
_logger.LogInformation("人员 {PersonnelId} 已被单位 {UnitId} 审批通过,等级:{Level}",
personnelId, approvedByUnitId, actualLevel);
return personnel;
}
///
/// 获取等级名称
///
private static string GetLevelName(PersonnelLevel? level)
{
return level switch
{
PersonnelLevel.Division => "师级人才",
PersonnelLevel.Regiment => "团级人才",
PersonnelLevel.Battalion => "营级人才",
PersonnelLevel.Company => "连级人才",
_ => "未定级"
};
}
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("军衔不能为空");
// Gender和Age已设置默认值,不需要验证
// IdNumber(士兵证号)是可选的,不需要验证必填
if (personnel.SubmittedByUnitId <= 0)
errors.Add("提交单位不能为空");
// 验证士兵证号格式(如果提供了)
// 注意:士兵证号不是身份证号,格式可能不同,这里移除18位的限制
// 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)
.Include(p => p.ApprovedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null)
return false;
// 已拒绝的人员不能审批
if (personnel.Status == PersonnelStatus.Rejected)
return false;
// 本单位不能审批自己提交的人员,必须由上级单位审批
if (user.OrganizationalUnitId == personnel.SubmittedByUnitId)
return false;
// 如果是已审批的人员(向上申报场景)
if (personnel.Status == PersonnelStatus.Approved && personnel.ApprovedByUnitId.HasValue)
{
// 用户单位层级必须高于已审批单位层级(数值越小层级越高)
if ((int)user.OrganizationalUnit!.Level >= (int)personnel.ApprovedByUnit!.Level)
return false;
// 向上申报场景:检查用户单位是否是当前审批单位的上级
var isParentOfApprovedUnit = await _organizationService.IsParentUnitAsync(
user.OrganizationalUnitId, personnel.ApprovedByUnitId.Value);
return isParentOfApprovedUnit;
}
// 首次审批场景:检查用户的组织单位是否是提交单位的上级
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作为系统操作
}
///
/// 发起向上申报请求
///
public async Task RequestUpgradeAsync(int personnelId, int requestByUnitId)
{
var personnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
if (personnel.Status != PersonnelStatus.Approved)
throw new ArgumentException("只有已审批的人员才能向上申报");
if (personnel.PendingUpgradeByUnitId.HasValue)
throw new ArgumentException("该人员已有待处理的向上申报请求");
var requestByUnit = await _context.OrganizationalUnits.FindAsync(requestByUnitId);
if (requestByUnit == null)
throw new ArgumentException("申报单位不存在");
// 师级人才不能再向上申报
if (personnel.ApprovedLevel == PersonnelLevel.Division)
throw new ArgumentException("师级人才不能再向上申报");
// 特殊情况:师部可以直接升级团级人才为师级
// 此时师部既是申报单位也是审批单位
if (requestByUnit.Level == OrganizationalLevel.Division &&
personnel.ApprovedLevel == PersonnelLevel.Regiment)
{
// 师部直接升级团级人才,不需要验证是否是审批单位
// 标记为待向上申报(由师部自己审批)
personnel.PendingUpgradeByUnitId = requestByUnitId;
await _context.SaveChangesAsync();
_logger.LogInformation("团级人才 {PersonnelId} 已由师部 {UnitId} 发起直接升级请求",
personnelId, requestByUnitId);
return personnel;
}
// 验证申报单位必须是当前审批单位
if (personnel.ApprovedByUnitId != requestByUnitId)
throw new ArgumentException("只有当前审批单位才能发起向上申报");
// 标记为待向上申报
personnel.PendingUpgradeByUnitId = requestByUnitId;
await _context.SaveChangesAsync();
_logger.LogInformation("人员 {PersonnelId} 已由单位 {UnitId} 发起向上申报请求",
personnelId, requestByUnitId);
return personnel;
}
///
/// 审批向上申报请求
///
public async Task ApproveUpgradeAsync(int personnelId, int approvedByUnitId)
{
var personnel = await _context.Personnel
.Include(p => p.SubmittedByUnit)
.Include(p => p.ApprovedByUnit)
.Include(p => p.PendingUpgradeByUnit)
.FirstOrDefaultAsync(p => p.Id == personnelId);
if (personnel == null)
throw new ArgumentException("人员记录不存在");
if (!personnel.PendingUpgradeByUnitId.HasValue)
throw new ArgumentException("该人员没有待处理的向上申报请求");
var approvedByUnit = await _context.OrganizationalUnits.FindAsync(approvedByUnitId);
if (approvedByUnit == null)
throw new ArgumentException("审批单位不存在");
_logger.LogInformation("ApproveUpgrade: personnelId={PersonnelId}, approvedByUnitId={ApprovedByUnitId}, pendingUpgradeByUnitId={PendingUpgradeByUnitId}, approvedByUnitLevel={Level}, personnelApprovedLevel={PersonnelLevel}",
personnelId, approvedByUnitId, personnel.PendingUpgradeByUnitId.Value, approvedByUnit.Level, personnel.ApprovedLevel);
var previousLevel = personnel.ApprovedLevel;
PersonnelLevel newLevel;
// 特殊情况:师部直接升级团级人才为师级
var isDivisionUnit = approvedByUnit.Level == OrganizationalLevel.Division;
var isRegimentPersonnel = personnel.ApprovedLevel == PersonnelLevel.Regiment;
_logger.LogInformation("检查条件: isDivisionUnit={IsDivision}, isRegimentPersonnel={IsRegiment}",
isDivisionUnit, isRegimentPersonnel);
if (isDivisionUnit && isRegimentPersonnel)
{
// 师部直接升级团级人才为师级
newLevel = PersonnelLevel.Division;
_logger.LogInformation("师部直接升级团级人才为师级");
}
else
{
// 验证审批单位必须是申报单位的上级
var isParent = await _organizationService.IsParentUnitAsync(approvedByUnitId, personnel.PendingUpgradeByUnitId.Value);
_logger.LogInformation("检查上级关系: isParent={IsParent}", isParent);
if (!isParent)
throw new ArgumentException("审批单位必须是申报单位的上级");
// 人才等级升级为申报单位的等级
newLevel = (PersonnelLevel)(int)personnel.PendingUpgradeByUnit!.Level;
}
personnel.ApprovedLevel = newLevel;
personnel.ApprovedByUnitId = approvedByUnitId;
personnel.ApprovedAt = DateTime.UtcNow;
personnel.PendingUpgradeByUnitId = null; // 清除待申报标记
await _context.SaveChangesAsync();
// 记录审批历史
var userId = await GetUserIdByUnitAsync(approvedByUnitId);
await RecordApprovalHistoryAsync(personnelId, PersonnelApprovalAction.LevelUpgraded,
PersonnelStatus.Approved, PersonnelStatus.Approved, previousLevel, newLevel,
userId, approvedByUnitId, $"向上申报通过,等级从{GetLevelName(previousLevel)}升级为{GetLevelName(newLevel)}");
_logger.LogInformation("人员 {PersonnelId} 向上申报已被单位 {UnitId} 审批通过,等级升级为 {Level}",
personnelId, approvedByUnitId, newLevel);
return personnel;
}
}