空闲教室与场地预约占用检查,现在对新发布课表优先查询 PublishedScheduleOccurrences。
查询直接按“学期 + 周次 + 星期 + 节次”命中投影索引,不再扫描周期规则并在应用层判断单双周。 历史已发布课表若尚未生成投影,自动回退到原规则表,兼容现有数据。 调停课审批后会重建受影响教学任务的已发布投影,因此占用结果同步更新。
This commit is contained in:
+27
-26
@@ -17,33 +17,34 @@ public sealed class ClassroomReservationAvailabilityService(AppDbContext db)
|
||||
var occupiedIds = new HashSet<Guid>();
|
||||
var (week, dayOfWeek) = ResolveTeachingWeek(term, reservationDate);
|
||||
|
||||
var scheduleEntries = await db.ScheduleEntries.AsNoTracking()
|
||||
.Where(entry =>
|
||||
entry.ClassroomId.HasValue &&
|
||||
entry.SchedulePlan!.AcademicTermId == term.Id &&
|
||||
entry.SchedulePlan.Status == SchedulePlanStatus.Published &&
|
||||
entry.DayOfWeek == dayOfWeek &&
|
||||
entry.StartWeek <= week &&
|
||||
entry.EndWeek >= week &&
|
||||
entry.StartPeriod < startPeriod + periodCount &&
|
||||
startPeriod < entry.StartPeriod + entry.PeriodCount)
|
||||
.Select(entry => new
|
||||
{
|
||||
entry.ClassroomId,
|
||||
entry.WeekPattern,
|
||||
entry.StartPeriod,
|
||||
entry.PeriodCount
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
foreach (var entry in scheduleEntries.Where(entry =>
|
||||
FreeClassroomRules.MatchesWeek(entry.WeekPattern, week) &&
|
||||
FreeClassroomRules.PeriodsOverlap(
|
||||
startPeriod,
|
||||
periodCount,
|
||||
entry.StartPeriod,
|
||||
entry.PeriodCount)))
|
||||
var hasProjection = await db.PublishedScheduleOccurrences.AsNoTracking()
|
||||
.AnyAsync(entry => entry.AcademicTermId == term.Id, cancellationToken);
|
||||
if (hasProjection)
|
||||
{
|
||||
occupiedIds.Add(entry.ClassroomId!.Value);
|
||||
var projectedRoomIds = await db.PublishedScheduleOccurrences.AsNoTracking()
|
||||
.Where(entry => entry.AcademicTermId == term.Id && entry.Week == week &&
|
||||
entry.DayOfWeek == dayOfWeek && entry.ClassroomId.HasValue &&
|
||||
entry.StartPeriod < startPeriod + periodCount &&
|
||||
startPeriod < entry.StartPeriod + entry.PeriodCount)
|
||||
.Select(entry => entry.ClassroomId!.Value)
|
||||
.ToListAsync(cancellationToken);
|
||||
occupiedIds.UnionWith(projectedRoomIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
var scheduleEntries = await db.ScheduleEntries.AsNoTracking()
|
||||
.Where(entry => entry.ClassroomId.HasValue &&
|
||||
entry.SchedulePlan!.AcademicTermId == term.Id &&
|
||||
entry.SchedulePlan.Status == SchedulePlanStatus.Published &&
|
||||
entry.DayOfWeek == dayOfWeek && entry.StartWeek <= week &&
|
||||
entry.EndWeek >= week && entry.StartPeriod < startPeriod + periodCount &&
|
||||
startPeriod < entry.StartPeriod + entry.PeriodCount)
|
||||
.Select(entry => new { entry.ClassroomId, entry.WeekPattern, entry.StartPeriod, entry.PeriodCount })
|
||||
.ToListAsync(cancellationToken);
|
||||
foreach (var entry in scheduleEntries.Where(entry =>
|
||||
FreeClassroomRules.MatchesWeek(entry.WeekPattern, week) &&
|
||||
FreeClassroomRules.PeriodsOverlap(startPeriod, periodCount, entry.StartPeriod, entry.PeriodCount)))
|
||||
occupiedIds.Add(entry.ClassroomId!.Value);
|
||||
}
|
||||
|
||||
var examRoomIds = await db.ExamSessions.AsNoTracking()
|
||||
|
||||
Reference in New Issue
Block a user