paiban/NPP.SmartSchedue.Api/Repositories/Time/ShiftUnavailabilityRepository.cs
Asoka.Wang 0a2e2d9b18 123
2025-09-02 18:52:35 +08:00

151 lines
5.6 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 NPP.SmartSchedue.Api.Contracts.Domain.Time;
using NPP.SmartSchedue.Api.Core.Repositories;
using ZhonTai.Admin.Core.Db;
using ZhonTai.Admin.Core.Db.Transaction;
using ZhonTai.Admin.Core.Repositories;
namespace NPP.SmartSchedue.Api.Repositories.Time;
/// <summary>
/// 班次不可用标记仓储实现
/// 提供高性能的班次不可用数据访问方法
/// </summary>
public class ShiftUnavailabilityRepository : AppRepositoryBase<ShiftUnavailabilityEntity>, IShiftUnavailabilityRepository
{
public ShiftUnavailabilityRepository(UnitOfWorkManagerCloud muowm) : base(muowm)
{
}
/// <summary>
/// 获取指定员工在指定日期范围内的不可用记录
/// 用于网格视图数据加载一次性获取整月数据避免N+1查询
/// </summary>
public async Task<List<ShiftUnavailabilityEntity>> GetByPersonnelAndDateRangeAsync(long personnelId, DateTime startDate, DateTime endDate)
{
return await Select
.Where(x => x.PersonnelId == personnelId &&
x.Date >= startDate.Date &&
x.Date <= endDate.Date)
.OrderBy(x => x.Date)
.OrderBy(x => x.ShiftId)
.ToListAsync();
}
/// <summary>
/// 获取指定日期和班次的不可用员工ID列表
/// 用于智能排班算法过滤不可用人员
/// </summary>
public async Task<List<long>> GetUnavailablePersonnelIdsAsync(DateTime date, long shiftId)
{
return await Select
.Where(x => x.Date.Date == date.Date && x.ShiftId == shiftId)
.GroupBy(x => x.PersonnelId) // 按员工分组,处理同一员工多条记录的情况
.ToListAsync(x => x.Key); // 只返回员工ID
}
/// <summary>
/// 检查人员班次的意愿
/// </summary>
/// <param name="date"></param>
/// <param name="shiftId"></param>
/// <param name="personnelId"></param>
/// <returns></returns>
public async Task<bool> CheckUnavailablePersonnelByShiftAsync(DateTime date, long shiftId, long personnelId)
{
return await Select
.AnyAsync(x => x.Date.Date == date.Date && x.ShiftId == shiftId && x.PersonnelId == personnelId );
}
/// <summary>
/// 获取指定日期所有班次的不可用员工分布
/// 用于某日的批量人员可用性查询
/// </summary>
public async Task<Dictionary<long, List<long>>> GetDailyUnavailablePersonnelAsync(DateTime date)
{
var records = await Select
.Where(x => x.Date.Date == date.Date)
.GroupBy(x => new { x.ShiftId, x.PersonnelId })
.ToListAsync(x => new { x.Key.ShiftId, x.Key.PersonnelId });
return records
.GroupBy(x => x.ShiftId)
.ToDictionary(
g => g.Key,
g => g.Select(x => x.PersonnelId).ToList()
);
}
/// <summary>
/// 批量获取日期范围内的不可用员工分布
/// 用于智能排班算法的批量优化查询
/// </summary>
public async Task<Dictionary<DateTime, Dictionary<long, List<long>>>> GetRangeUnavailablePersonnelAsync(DateTime startDate, DateTime endDate)
{
var records = await Select
.Where(x => x.Date >= startDate.Date && x.Date <= endDate.Date)
.GroupBy(x => new { x.Date, x.ShiftId, x.PersonnelId })
.ToListAsync(x => new { x.Key.Date, x.Key.ShiftId, x.Key.PersonnelId });
return records
.GroupBy(x => x.Date.Date)
.ToDictionary(
dateGroup => dateGroup.Key,
dateGroup => dateGroup
.GroupBy(x => x.ShiftId)
.ToDictionary(
shiftGroup => shiftGroup.Key,
shiftGroup => shiftGroup.Select(x => x.PersonnelId).ToList()
)
);
}
/// <summary>
/// 检查指定员工在指定日期和班次是否已有不可用记录
/// 用于避免重复插入和批量操作中的冲突检测
/// </summary>
public async Task<bool> ExistsAsync(long personnelId, DateTime date, long shiftId)
{
return await Select
.Where(x => x.PersonnelId == personnelId &&
x.Date.Date == date.Date &&
x.ShiftId == shiftId)
.AnyAsync();
}
/// <summary>
/// 删除指定条件的记录
/// 用于批量操作中的覆盖模式和数据清理
/// </summary>
public async Task<int> DeleteByConditionAsync(long personnelId, DateTime date, long? shiftId = null)
{
var query = Orm.Delete<ShiftUnavailabilityEntity>()
.Where(x => x.PersonnelId == personnelId && x.Date.Date == date.Date);
if (shiftId.HasValue)
{
query = query.Where(x => x.ShiftId == shiftId.Value);
}
return await query.ExecuteAffrowsAsync();
}
/// <summary>
/// 获取统计信息
/// 按原因类型统计指定员工在指定日期范围内的不可用次数
/// </summary>
public async Task<Dictionary<int, int>> GetStatisticsAsync(long personnelId, DateTime startDate, DateTime endDate)
{
var results = await Select
.Where(x => x.PersonnelId == personnelId &&
x.Date >= startDate.Date &&
x.Date <= endDate.Date)
.GroupBy(x => x.ReasonType)
.ToListAsync(x => new { ReasonType = x.Key, Count = x.Count() });
return results.ToDictionary(x => x.ReasonType, x => x.Count);
}
}