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.Contracts.Services.Time; using NPP.SmartSchedue.Api.Contracts.Services.Time.Input; using NPP.SmartSchedue.Api.Services.Time; using ZhonTai.DynamicApi; using ZhonTai.DynamicApi.Attributes; namespace NPP.SmartSchedue.Api.Services.Personnel; /// /// 人员综合服务 /// [DynamicApi(Area = "app")] public class PersonService : BaseService, IPersonService, IDynamicApi { private readonly IPersonnelWorkLimitService _personnelWorkLimitService; private readonly IPersonnelQualificationService _personnelQualificationService; private readonly IQualificationService _qualificationService; private readonly IEmployeeLeaveService _employeeLeaveService; private readonly IShiftService _shiftService; private readonly ShiftUnavailabilityService _shiftUnavailabilityService; public PersonService( IPersonnelWorkLimitService personnelWorkLimitService, IPersonnelQualificationService personnelQualificationService, IQualificationService qualificationService, IEmployeeLeaveService employeeLeaveService, ShiftUnavailabilityService shiftUnavailabilityService, IShiftService shiftService) { _personnelWorkLimitService = personnelWorkLimitService; _personnelQualificationService = personnelQualificationService; _qualificationService = qualificationService; _employeeLeaveService = employeeLeaveService; _shiftUnavailabilityService = shiftUnavailabilityService; _shiftService = shiftService; } /// /// 根据资质IDs、班次ID、工作日期,查询非请假的、有资质的人员 /// /// 资质ID列表 /// 班次ID /// 工作日期(将结合班次时间计算实际工作时间段) /// public async Task> GetAvailablePersonnelAsync( string qualificationIds, long shiftId, DateTime workStartTime) { var availablePersonnel = new List(); // 获取所有有指定资质的人员基础信息 var qualifiedPersonnelList = await _personnelQualificationService.GetPersonnelIdsByQualificationIdsAsync(qualificationIds); var unavailablePersonnels = await _shiftUnavailabilityService.GetUnavailablePersonnelAsync(workStartTime, shiftId); // 检查每个有资质的人员是否在指定时间段内有意愿 foreach (var personnel in qualifiedPersonnelList) { // 如果没有请假,则添加到可用人员列表 if (!unavailablePersonnels.Any(p => p == personnel.Id)) { // 获取人员资质信息 var qualifications = await _personnelQualificationService.GetActiveQualificationsByPersonnelIdAsync(personnel.Id); availablePersonnel.Add(new AvailablePersonnelOutput { PersonnelId = personnel.Id, PersonnelName = personnel.Name, ShiftId = shiftId, Qualifications = qualifications, }); } } return availablePersonnel; } /// /// 检查人员是否具备指定资质 /// /// 人员ID /// 资质ID /// public async Task HasQualificationAsync(long personnelId, long qualificationId) { var input = new PageInput { Filter = new PersonnelQualificationGetPageInput { PersonnelId = personnelId, QualificationId = qualificationId, IsActive = true }, PageSize = 1, CurrentPage = 1 }; var result = await _personnelQualificationService.GetPageAsync(input); return result.Total > 0; } /// /// 获取所有人员池(用于智能分配) /// 深度业务思考:从资质表获取所有关联人员并去重,确保五层决策模型的完整性 /// /// 是否包含资质信息 /// 完整的人员池,用于后续的五层决策筛选 public async Task> GetAllPersonnelPoolAsync(bool includeQualifications = false) { try { // 从资质表获取所有有资质的人员ID,然后去重 // 这确保了获取的人员池都是有资质记录的人员 var allQualificationPersonnel = await _personnelQualificationService.GetAllPersonnelWithQualificationsAsync(); if (allQualificationPersonnel == null || !allQualificationPersonnel.Any()) { return new List(); } // 按人员ID去重分组,获取人员基础信息 var groupedByPersonnel = allQualificationPersonnel .Where(pq => pq.PersonnelId > 0) .GroupBy(pq => pq.PersonnelId) .Select(g => g.First()) // 每个人员只取一条记录来获取基础信息 .ToList(); var personnelPoolOutputs = new List(); foreach (var qualificationRecord in groupedByPersonnel) { var poolOutput = new PersonnelPoolOutput { Id = qualificationRecord.PersonnelId, PersonnelName = qualificationRecord.PersonnelName, IsActive = true, }; // 如果需要包含资质信息 if (includeQualifications) { poolOutput.Qualifications = await _personnelQualificationService.GetActiveQualificationsByPersonnelIdAsync( qualificationRecord.PersonnelId); } personnelPoolOutputs.Add(poolOutput); } return personnelPoolOutputs.OrderBy(p => p.PersonnelCode).ToList(); } catch (Exception ex) { return new List(); } } }