171 lines
6.7 KiB
C#
171 lines
6.7 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// 人员综合服务
|
||
/// </summary>
|
||
[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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据资质IDs、班次ID、工作日期,查询非请假的、有资质的人员
|
||
/// </summary>
|
||
/// <param name="qualificationIds">资质ID列表</param>
|
||
/// <param name="shiftId">班次ID</param>
|
||
/// <param name="workStartTime">工作日期(将结合班次时间计算实际工作时间段)</param>
|
||
/// <returns></returns>
|
||
public async Task<List<AvailablePersonnelOutput>> GetAvailablePersonnelAsync(
|
||
string qualificationIds,
|
||
long shiftId,
|
||
DateTime workStartTime)
|
||
{
|
||
var availablePersonnel = new List<AvailablePersonnelOutput>();
|
||
|
||
// 获取所有有指定资质的人员基础信息
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查人员是否具备指定资质
|
||
/// </summary>
|
||
/// <param name="personnelId">人员ID</param>
|
||
/// <param name="qualificationId">资质ID</param>
|
||
/// <returns></returns>
|
||
public async Task<bool> HasQualificationAsync(long personnelId, long qualificationId)
|
||
{
|
||
var input = new PageInput<PersonnelQualificationGetPageInput>
|
||
{
|
||
Filter = new PersonnelQualificationGetPageInput
|
||
{
|
||
PersonnelId = personnelId,
|
||
QualificationId = qualificationId,
|
||
IsActive = true
|
||
},
|
||
PageSize = 1,
|
||
CurrentPage = 1
|
||
};
|
||
|
||
var result = await _personnelQualificationService.GetPageAsync(input);
|
||
return result.Total > 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有人员池(用于智能分配)
|
||
/// 深度业务思考:从资质表获取所有关联人员并去重,确保五层决策模型的完整性
|
||
/// </summary>
|
||
/// <param name="includeQualifications">是否包含资质信息</param>
|
||
/// <returns>完整的人员池,用于后续的五层决策筛选</returns>
|
||
public async Task<List<PersonnelPoolOutput>> GetAllPersonnelPoolAsync(bool includeQualifications = false)
|
||
{
|
||
try
|
||
{
|
||
// 从资质表获取所有有资质的人员ID,然后去重
|
||
// 这确保了获取的人员池都是有资质记录的人员
|
||
var allQualificationPersonnel = await _personnelQualificationService.GetAllPersonnelWithQualificationsAsync();
|
||
|
||
if (allQualificationPersonnel == null || !allQualificationPersonnel.Any())
|
||
{
|
||
return new List<PersonnelPoolOutput>();
|
||
}
|
||
|
||
// 按人员ID去重分组,获取人员基础信息
|
||
var groupedByPersonnel = allQualificationPersonnel
|
||
.Where(pq => pq.PersonnelId > 0)
|
||
.GroupBy(pq => pq.PersonnelId)
|
||
.Select(g => g.First()) // 每个人员只取一条记录来获取基础信息
|
||
.ToList();
|
||
|
||
var personnelPoolOutputs = new List<PersonnelPoolOutput>();
|
||
|
||
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<PersonnelPoolOutput>();
|
||
}
|
||
}
|
||
} |