Asoka.Wang 21f044712c 1
2025-08-27 18:39:19 +08:00

190 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 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;
public PersonService(
IPersonnelWorkLimitService personnelWorkLimitService,
IPersonnelQualificationService personnelQualificationService,
IQualificationService qualificationService,
IEmployeeLeaveService employeeLeaveService,
IShiftService shiftService)
{
_personnelWorkLimitService = personnelWorkLimitService;
_personnelQualificationService = personnelQualificationService;
_qualificationService = qualificationService;
_employeeLeaveService = employeeLeaveService;
_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 shift = await _shiftService.GetAsync(shiftId);
if (shift == null)
{
return availablePersonnel; // 如果班次不存在,返回空列表
}
// 计算实际工作时间段
var workDate = workStartTime.Date; // 取日期部分
var actualWorkStartTime = workDate.Add(shift.StartTime);
var actualWorkEndTime = workDate.Add(shift.EndTime);
// 处理跨天班次如夜班22:00-06:00
if (shift.EndTime < shift.StartTime)
{
actualWorkEndTime = actualWorkEndTime.AddDays(1);
}
// 获取所有有指定资质的人员基础信息
var qualifiedPersonnelList = await _personnelQualificationService.GetPersonnelIdsByQualificationIdsAsync(qualificationIds);
// 检查每个有资质的人员是否在指定时间段内请假
foreach (var personnel in qualifiedPersonnelList)
{
// 注意这里假设PersonnelId对应EmployeeId如果不是需要添加映射逻辑
var isOnLeave = await _employeeLeaveService.HasApprovedLeaveInTimeRangeAsync(
personnel.Id,
actualWorkStartTime,
actualWorkEndTime);
// 如果没有请假,则添加到可用人员列表
if (!isOnLeave)
{
// 获取人员资质信息
var qualifications = await _personnelQualificationService.GetActiveQualificationsByPersonnelIdAsync(personnel.Id);
availablePersonnel.Add(new AvailablePersonnelOutput
{
PersonnelId = personnel.Id,
PersonnelName = personnel.Name,
ShiftId = shiftId,
AvailableStartTime = actualWorkStartTime,
AvailableEndTime = actualWorkEndTime,
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>();
}
}
}