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; /// /// 班次不可用标记仓储实现 /// 提供高性能的班次不可用数据访问方法 /// public class ShiftUnavailabilityRepository : AppRepositoryBase, IShiftUnavailabilityRepository { public ShiftUnavailabilityRepository(UnitOfWorkManagerCloud muowm) : base(muowm) { } /// /// 获取指定员工在指定日期范围内的不可用记录 /// 用于网格视图数据加载,一次性获取整月数据避免N+1查询 /// public async Task> 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(); } /// /// 获取指定日期和班次的不可用员工ID列表 /// 用于智能排班算法过滤不可用人员 /// public async Task> 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 } /// /// 检查人员班次的意愿 /// /// /// /// /// public async Task CheckUnavailablePersonnelByShiftAsync(DateTime date, long shiftId, long personnelId) { return await Select .AnyAsync(x => x.Date.Date == date.Date && x.ShiftId == shiftId && x.PersonnelId == personnelId ); } /// /// 获取指定日期所有班次的不可用员工分布 /// 用于某日的批量人员可用性查询 /// public async Task>> 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() ); } /// /// 批量获取日期范围内的不可用员工分布 /// 用于智能排班算法的批量优化查询 /// public async Task>>> 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() ) ); } /// /// 检查指定员工在指定日期和班次是否已有不可用记录 /// 用于避免重复插入和批量操作中的冲突检测 /// public async Task ExistsAsync(long personnelId, DateTime date, long shiftId) { return await Select .Where(x => x.PersonnelId == personnelId && x.Date.Date == date.Date && x.ShiftId == shiftId) .AnyAsync(); } /// /// 删除指定条件的记录 /// 用于批量操作中的覆盖模式和数据清理 /// public async Task DeleteByConditionAsync(long personnelId, DateTime date, long? shiftId = null) { var query = Orm.Delete() .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(); } /// /// 获取统计信息 /// 按原因类型统计指定员工在指定日期范围内的不可用次数 /// public async Task> 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); } }