考试排考
This commit is contained in:
@@ -109,6 +109,11 @@ public sealed class TimetableDataService(AppDbContext db)
|
||||
term.Id,
|
||||
studentId,
|
||||
cancellationToken);
|
||||
|
||||
// Load exam sessions for student/teacher timetables
|
||||
var examEntries = await LoadExamEntriesAsync(
|
||||
resourceType, resourceId, term.Id, studentId, slots, cancellationToken);
|
||||
|
||||
return new TimetableData(
|
||||
term,
|
||||
subject,
|
||||
@@ -117,7 +122,8 @@ public sealed class TimetableDataService(AppDbContext db)
|
||||
plan,
|
||||
slots,
|
||||
entries,
|
||||
flexibleCourses);
|
||||
flexibleCourses,
|
||||
examEntries);
|
||||
}
|
||||
|
||||
private async Task<TimetableSubjectDto?> LoadSubjectAsync(
|
||||
@@ -286,6 +292,101 @@ public sealed class TimetableDataService(AppDbContext db)
|
||||
x.Notes))
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<List<TimetableEntryDto>> LoadExamEntriesAsync(
|
||||
TimetableResourceType resourceType,
|
||||
Guid resourceId,
|
||||
Guid academicTermId,
|
||||
Guid? studentId,
|
||||
IReadOnlyList<TimetableSlotDto> slots,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (resourceType == TimetableResourceType.Classroom) return [];
|
||||
|
||||
var slotLookup = slots.ToDictionary(x => x.PeriodNumber);
|
||||
|
||||
IQueryable<ExamSession> source = db.ExamSessions.AsNoTracking()
|
||||
.Where(x => x.ExamPlan!.AcademicTermId == academicTermId &&
|
||||
x.ExamPlan.Status == ExamPlanStatus.Published &&
|
||||
x.ClassroomId != null);
|
||||
|
||||
if (resourceType == TimetableResourceType.Teacher)
|
||||
{
|
||||
source = source.Where(x =>
|
||||
x.Invigilators.Any(i => i.TeacherId == resourceId));
|
||||
}
|
||||
else if (studentId.HasValue)
|
||||
{
|
||||
source = source.Where(x =>
|
||||
db.CourseEnrollments.Any(e =>
|
||||
e.StudentId == studentId.Value &&
|
||||
e.Status == CourseEnrollmentStatus.Enrolled &&
|
||||
e.CourseSelectionOffering!.TeachingTaskId == x.TeachingTaskId));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Class timetable: exams for the class's teaching tasks
|
||||
source = source.Where(x =>
|
||||
x.TeachingTask!.Classes.Any(c =>
|
||||
c.AdministrativeClassId == resourceId));
|
||||
}
|
||||
|
||||
var sessions = await source
|
||||
.OrderBy(x => x.ExamDate)
|
||||
.ThenBy(x => x.StartPeriod)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.TeachingTaskId,
|
||||
x.TeachingTask!.TaskNumber,
|
||||
TaskName = x.TeachingTask.Name,
|
||||
CourseCode = x.TeachingTask.Course!.Code,
|
||||
CourseName = x.TeachingTask.Course.Name,
|
||||
TeacherNames = x.TeachingTask.Teachers
|
||||
.OrderByDescending(t => t.IsPrimary)
|
||||
.Select(t => t.Teacher!.Name),
|
||||
ClassNames = x.TeachingTask.Classes
|
||||
.Select(c => c.AdministrativeClass!.Name),
|
||||
ClassroomName = x.Classroom!.Name,
|
||||
BuildingName = x.Classroom.Building!.Name,
|
||||
CampusName = x.Classroom.Building.Campus!.Name,
|
||||
x.ExamDate,
|
||||
x.StartPeriod,
|
||||
x.PeriodCount,
|
||||
x.ExamPlan!.Name,
|
||||
InvigilatorNames = x.Invigilators
|
||||
.Select(i => i.Teacher!.Name),
|
||||
x.Notes
|
||||
})
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
return sessions.Select(x =>
|
||||
{
|
||||
var dayOfWeek = x.ExamDate.DayOfWeek == 0 ? 7 : (int)x.ExamDate.DayOfWeek;
|
||||
return new TimetableEntryDto(
|
||||
x.Id,
|
||||
x.TeachingTaskId,
|
||||
x.TaskNumber,
|
||||
x.TaskName,
|
||||
x.CourseCode,
|
||||
x.CourseName,
|
||||
x.TeacherNames.Concat(
|
||||
new[] { "监考:" + string.Join("、", x.InvigilatorNames) }),
|
||||
x.ClassNames,
|
||||
x.ClassroomName,
|
||||
x.BuildingName,
|
||||
x.CampusName,
|
||||
dayOfWeek,
|
||||
x.StartPeriod,
|
||||
x.PeriodCount,
|
||||
1, 1,
|
||||
WeekPattern.All,
|
||||
x.Notes,
|
||||
true,
|
||||
x.Name,
|
||||
x.ExamDate);
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public enum TimetableResourceType
|
||||
@@ -303,7 +404,8 @@ public sealed record TimetableData(
|
||||
TimetablePlanDto? Plan,
|
||||
IReadOnlyList<TimetableSlotDto> Slots,
|
||||
IReadOnlyList<TimetableEntryDto> Entries,
|
||||
IReadOnlyList<FlexibleCourseDto> FlexibleCourses);
|
||||
IReadOnlyList<FlexibleCourseDto> FlexibleCourses,
|
||||
IReadOnlyList<TimetableEntryDto> ExamEntries);
|
||||
|
||||
public sealed record TimetableTermDto(
|
||||
Guid Id,
|
||||
@@ -362,7 +464,10 @@ public sealed record TimetableEntryDto(
|
||||
int StartWeek,
|
||||
int EndWeek,
|
||||
WeekPattern WeekPattern,
|
||||
string? Notes);
|
||||
string? Notes,
|
||||
bool IsExam = false,
|
||||
string? ExamPlanName = null,
|
||||
DateOnly? ExamDate = null);
|
||||
|
||||
public sealed record FlexibleCourseDto(
|
||||
Guid Id,
|
||||
|
||||
Reference in New Issue
Block a user