using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ZhonTai.Admin.Core.Dto;
using ZhonTai.Admin.Services;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel.Input;
using NPP.SmartSchedue.Api.Contracts.Services.Personnel.Output;
using NPP.SmartSchedue.Api.Repositories.Personnel;
using NPP.SmartSchedue.Api.Contracts.Domain.Personnel;
using ZhonTai.Admin.Core.Consts;
using ZhonTai.DynamicApi;
using ZhonTai.DynamicApi.Attributes;
using ZhonTai.Admin.Domain.User;
namespace NPP.SmartSchedue.Api.Services.Personnel;
///
/// 人员资质绑定服务
///
[DynamicApi(Area = "app")]
public class PersonnelQualificationService : BaseService, IPersonnelQualificationService, IDynamicApi
{
private readonly PersonnelQualificationRepository _personnelQualificationRepository;
private readonly QualificationRepository _qualificationRepository;
public PersonnelQualificationService(
PersonnelQualificationRepository personnelQualificationRepository,
QualificationRepository qualificationRepository)
{
_personnelQualificationRepository = personnelQualificationRepository;
_qualificationRepository = qualificationRepository;
}
///
/// 查询
///
///
///
public async Task GetAsync(long id)
{
var output = await _personnelQualificationRepository.Select
.WhereDynamic(id)
.ToOneAsync();
return output;
}
///
/// 查询分页
///
///
///
[HttpPost]
public async Task> GetPageAsync(PageInput input)
{
var list = await _personnelQualificationRepository.Select
.WhereIf(input.Filter?.PersonnelId.HasValue == true, a => a.PersonnelId == input.Filter.PersonnelId)
.WhereIf(input.Filter?.QualificationId.HasValue == true, a => a.QualificationId == input.Filter.QualificationId)
.WhereIf(input.Filter?.IsActive.HasValue == true, a => a.IsActive == input.Filter.IsActive)
.Count(out var total)
.OrderByDescending(a => a.Id)
.Page(input.CurrentPage, input.PageSize)
.ToListAsync();
var data = new PageOutput()
{
List = list,
Total = total
};
return data;
}
///
/// 添加
///
///
///
public async Task AddAsync(PersonnelQualificationAddInput input)
{
var entity = Mapper.Map(input);
var result = await _personnelQualificationRepository.InsertAsync(entity);
return result.Id;
}
///
/// 修改
///
///
///
public async Task UpdateAsync(PersonnelQualificationUpdateInput input)
{
var entity = await _personnelQualificationRepository.GetAsync(input.Id);
Mapper.Map(input, entity);
await _personnelQualificationRepository.UpdateAsync(entity);
}
///
/// 删除
///
///
///
public async Task DeleteAsync(long id)
{
await _personnelQualificationRepository.DeleteAsync(id);
}
///
/// 软删除
///
///
///
public async Task SoftDeleteAsync(long id)
{
await _personnelQualificationRepository.SoftDeleteAsync(id);
}
///
/// 批量软删除
///
///
///
public async Task BatchSoftDeleteAsync(long[] ids)
{
await _personnelQualificationRepository.SoftDeleteAsync(ids);
}
///
/// 根据资质ID列表获取具有这些资质的人员基础信息列表(ID + 姓名)
///
/// 资质ID列表
///
public async Task> GetPersonnelIdsByQualificationIdsAsync(long[] qualificationIds)
{
var personnelInfoMap = new Dictionary();
var qualifiedPersonnel = await _personnelQualificationRepository.Select
.Where(pq => qualificationIds.Contains(pq.QualificationId) && pq.IsActive)
.ToListAsync(p => new PersonnelBasicInfo
{
Id = p.PersonnelId,
Name = p.PersonnelName // 临时使用默认格式
});
// 去重处理
foreach (var personnel in qualifiedPersonnel)
{
personnelInfoMap[personnel.Id] = personnel;
}
return personnelInfoMap.Values.ToList();
}
///
/// 根据资质ID字符串(逗号分隔)获取具有这些资质的人员基础信息列表(ID + 姓名)
///
/// 资质ID字符串,使用逗号分隔
///
public async Task> GetPersonnelIdsByQualificationIdsAsync(string qualificationIds)
{
// 检查输入参数的有效性
if (string.IsNullOrWhiteSpace(qualificationIds))
{
return new List();
}
try
{
// 解析逗号分隔的字符串为long数组
var qualificationIdArray = qualificationIds
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(id => id.Trim())
.Where(id => !string.IsNullOrWhiteSpace(id))
.Select(long.Parse)
.ToArray();
// 调用原有的数组版本方法
return await GetPersonnelIdsByQualificationIdsAsync(qualificationIdArray);
}
catch (FormatException)
{
// 如果解析失败,返回空列表而不是抛出异常
return new List();
}
catch (OverflowException)
{
// 如果数值超出范围,返回空列表而不是抛出异常
return new List();
}
}
///
/// 根据人员ID获取其所有有效资质信息
///
/// 人员ID
///
public async Task> GetActiveQualificationsByPersonnelIdAsync(long personnelId)
{
var input = new PageInput
{
Filter = new PersonnelQualificationGetPageInput { PersonnelId = personnelId, IsActive = true },
PageSize = 1000,
CurrentPage = 1
};
var result = await GetPageAsync(input);
return result.List?.ToList() ?? new List();
}
///
/// 获取所有有资质记录的人员列表(用于人员池构建)
/// 深度业务思考:从资质表获取所有关联人员,确保智能分配系统的人员池完整性
///
/// 所有有资质记录的人员资质信息
public async Task> GetAllPersonnelWithQualificationsAsync()
{
try
{
// 获取所有有效的人员资质记录
// 这里不分页,获取全量数据用于构建人员池
var entities = await _personnelQualificationRepository.Select
.Where(pq => pq.PersonnelId > 0) // 确保有有效的人员ID
.OrderBy(pq => pq.PersonnelId)
.ToListAsync();
// 手动映射确保PersonnelName字段被正确传递
var results = entities.Select(entity => new PersonnelQualificationGetPageOutput
{
Id = entity.Id,
PersonnelId = entity.PersonnelId,
PersonnelName = entity.PersonnelName, // 【关键修复】确保人员姓名被正确映射
QualificationId = entity.QualificationId,
QualificationLevel = entity.QualificationLevel,
ExpiryDate = entity.ExpiryDate,
ExpiryWarningDays = entity.ExpiryWarningDays,
RenewalDate = entity.RenewalDate,
IsActive = entity.IsActive
}).ToList();
return results;
}
catch (Exception ex)
{
return new List();
}
}
///
/// 根据人员ID获取其所有资质记录(包括无效的)
///
/// 人员ID
/// 人员的所有资质记录
public async Task> GetByPersonnelIdAsync(long personnelId)
{
try
{
// 获取指定人员的所有资质记录,不论是否有效
var entities = await _personnelQualificationRepository.Select
.Where(pq => pq.PersonnelId == personnelId)
.OrderBy(pq => pq.QualificationId)
.ToListAsync();
// 手动映射确保PersonnelName字段被正确传递
var results = entities.Select(entity => new PersonnelQualificationGetPageOutput
{
Id = entity.Id,
PersonnelId = entity.PersonnelId,
PersonnelName = entity.PersonnelName, // 【关键修复】确保人员姓名被正确映射
QualificationId = entity.QualificationId,
QualificationLevel = entity.QualificationLevel,
ExpiryDate = entity.ExpiryDate,
ExpiryWarningDays = entity.ExpiryWarningDays,
RenewalDate = entity.RenewalDate,
IsActive = entity.IsActive
}).ToList();
return results;
}
catch (Exception ex)
{
return new List();
}
}
///
/// 根据人员ID获取其所有有效的资质实体列表(用于智能分配系统资质匹配)
/// 深度业务思考:智能分配系统需要完整的资质实体信息进行精确匹配计算
/// 1. 只获取有效状态的资质记录(IsActive = true)
/// 2. 检查资质有效期,排除已过期资质
/// 3. 返回完整实体信息供复杂业务逻辑使用
/// 4. 异常处理确保系统稳定性
///
/// 人员ID
/// 人员有效资质实体列表
public async Task> GetPersonnelQualificationsAsync(long personnelId)
{
try
{
// 深度思考:智能分配系统需要精确的资质匹配
// 必须同时满足:1. 状态有效 2. 未过期 3. 有效的人员关联
var currentTime = DateTime.Now;
var qualificationEntities = await _personnelQualificationRepository.Select
.Where(pq => pq.PersonnelId == personnelId &&
pq.IsActive && // 必须是激活状态
(pq.ExpiryDate == null || pq.ExpiryDate > currentTime)) // 未过期或永久有效
.OrderBy(pq => pq.QualificationId)
.ToListAsync();
return qualificationEntities ?? new List();
}
catch (Exception ex)
{
return new List();
}
}
///
/// 获取人员资质统计信息(横坐标为资质,纵坐标为人员数量)
///
/// 人员资质统计结果
public async Task GetPersonnelQualificationStatisticsAsync()
{
try
{
// 获取所有有效的人员资质记录
var activeQualifications = await _personnelQualificationRepository.Select
.Where(pq => pq.IsActive && (pq.ExpiryDate == null || pq.ExpiryDate > DateTime.Now))
.ToListAsync(pq => new { pq.QualificationId, pq.PersonnelId });
// 按资质ID分组并统计每个资质的人员数量
var qualificationStatistics = activeQualifications
.GroupBy(q => q.QualificationId)
.Select(g => new
{
QualificationId = g.Key,
PersonnelCount = g.Select(x => x.PersonnelId).Distinct().Count()
})
.ToList();
// 获取所有资质的名称
var qualificationIds = qualificationStatistics.Select(q => q.QualificationId).ToArray();
var qualifications = await _qualificationRepository.Select
.Where(q => qualificationIds.Contains(q.Id))
.ToListAsync(q => new { q.Id, q.Name });
var qualificationsDict = qualifications.ToDictionary(q => q.Id, q => q.Name);
// 构建统计结果
var statistics = qualificationStatistics
.Select(stat => new PersonnelQualificationStatistics
{
QualificationId = stat.QualificationId,
QualificationName = qualificationsDict.ContainsKey(stat.QualificationId)
? qualificationsDict[stat.QualificationId]
: $"未知资质({stat.QualificationId})",
PersonnelCount = stat.PersonnelCount
})
.ToList();
return new PersonnelQualificationStatisticsResult
{
Statistics = statistics,
GeneratedTime = DateTime.Now
};
}
catch (Exception ex)
{
// 发生异常时返回空的统计结果
return new PersonnelQualificationStatisticsResult
{
Statistics = new List(),
GeneratedTime = DateTime.Now
};
}
}
///
/// 获取预警期内即将到期的人员资质清单
///
/// 基准日期(通常为 DateTime.Today)
/// 限定人员范围(可选)
/// 是否包含已过期记录
///
public async Task> GetExpiringAsync(DateTime today, IList personnelIds = null, bool includeExpired = false)
{
var baseDate = today.Date;
var select = _personnelQualificationRepository.Select
.Where(pq => pq.IsActive)
.Where(pq => pq.ExpiryDate != null)
.Where(pq => pq.ExpiryWarningDays != null && pq.ExpiryWarningDays > 0);
if (personnelIds != null && personnelIds.Count > 0)
{
select = select.Where(pq => personnelIds.Contains(pq.PersonnelId));
}
var list = await select.ToListAsync();
// 批量查询资质名称,避免 N+1
var qIds = list.Select(x => x.QualificationId).Distinct().ToArray();
var qNameMap = qIds.Length == 0
? new Dictionary()
: (await _qualificationRepository.Select
.Where(q => qIds.Contains(q.Id))
.ToListAsync(q => new { q.Id, q.Name }))
.ToDictionary(x => x.Id, x => x.Name ?? string.Empty);
var result = new List(list.Count);
foreach (var it in list)
{
var expiry = it.ExpiryDate.Value.Date;
var daysLeft = (int)Math.Floor((expiry - baseDate).TotalDays);
bool inWindow = includeExpired
? daysLeft <= it.ExpiryWarningDays.Value
: daysLeft >= 0 && daysLeft <= it.ExpiryWarningDays.Value;
if (!inWindow) continue;
result.Add(new ExpiringQualificationItemOutput
{
PersonnelId = it.PersonnelId,
PersonnelName = it.PersonnelName,
PersonnelCode = it.PersonnelCode,
QualificationId = it.QualificationId,
QualificationLevel = it.QualificationLevel,
ExpiryDate = it.ExpiryDate,
DaysLeft = daysLeft,
QualificationName = qNameMap.TryGetValue(it.QualificationId, out var qn) ? qn : string.Empty
});
}
return result
.OrderBy(x => x.DaysLeft)
.ThenBy(x => x.ExpiryDate)
.ToList();
}
}