补考系统
This commit is contained in:
@@ -55,6 +55,12 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
public DbSet<ExamSession> ExamSessions => Set<ExamSession>();
|
||||
public DbSet<ExamSessionInvigilator> ExamSessionInvigilators =>
|
||||
Set<ExamSessionInvigilator>();
|
||||
public DbSet<MakeupExamPlan> MakeupExamPlans => Set<MakeupExamPlan>();
|
||||
public DbSet<MakeupExamSession> MakeupExamSessions => Set<MakeupExamSession>();
|
||||
public DbSet<MakeupExamSessionInvigilator> MakeupExamSessionInvigilators =>
|
||||
Set<MakeupExamSessionInvigilator>();
|
||||
public DbSet<MakeupExamEnrollment> MakeupExamEnrollments =>
|
||||
Set<MakeupExamEnrollment>();
|
||||
public DbSet<CourseAdjustment> CourseAdjustments => Set<CourseAdjustment>();
|
||||
public DbSet<CourseExemption> CourseExemptions => Set<CourseExemption>();
|
||||
public DbSet<DeferredExam> DeferredExams => Set<DeferredExam>();
|
||||
@@ -598,6 +604,52 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
entity.HasOne(x => x.Teacher).WithMany()
|
||||
.HasForeignKey(x => x.TeacherId).OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
builder.Entity<MakeupExamPlan>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Name).HasMaxLength(120);
|
||||
entity.Property(x => x.Notes).HasMaxLength(500);
|
||||
entity.HasIndex(x => new { x.AcademicTermId, x.Status });
|
||||
entity.HasOne(x => x.AcademicTerm).WithMany()
|
||||
.HasForeignKey(x => x.AcademicTermId).OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
builder.Entity<MakeupExamSession>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Notes).HasMaxLength(500);
|
||||
entity.HasIndex(x => new { x.MakeupExamPlanId, x.StartsAt });
|
||||
entity.HasIndex(x => x.TeachingTaskId);
|
||||
entity.HasIndex(x => new { x.MakeupExamPlanId, x.ExamDate });
|
||||
entity.HasIndex(x => x.RequiredBuildingId);
|
||||
entity.HasOne(x => x.MakeupExamPlan).WithMany(x => x.Sessions)
|
||||
.HasForeignKey(x => x.MakeupExamPlanId).OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne(x => x.TeachingTask).WithMany()
|
||||
.HasForeignKey(x => x.TeachingTaskId).OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(x => x.Classroom).WithMany()
|
||||
.HasForeignKey(x => x.ClassroomId).OnDelete(DeleteBehavior.SetNull);
|
||||
entity.HasOne(x => x.RequiredBuilding).WithMany()
|
||||
.HasForeignKey(x => x.RequiredBuildingId).OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
builder.Entity<MakeupExamSessionInvigilator>(entity =>
|
||||
{
|
||||
entity.HasKey(x => new { x.MakeupExamSessionId, x.TeacherId });
|
||||
entity.HasOne(x => x.MakeupExamSession).WithMany(x => x.Invigilators)
|
||||
.HasForeignKey(x => x.MakeupExamSessionId).OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne(x => x.Teacher).WithMany()
|
||||
.HasForeignKey(x => x.TeacherId).OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
builder.Entity<MakeupExamEnrollment>(entity =>
|
||||
{
|
||||
entity.HasKey(x => new { x.MakeupExamSessionId, x.StudentId });
|
||||
entity.HasIndex(x => new { x.StudentId, x.MakeupExamSessionId });
|
||||
entity.Property(x => x.MakeupScore).HasPrecision(5, 1);
|
||||
entity.HasOne(x => x.MakeupExamSession).WithMany(x => x.Enrollments)
|
||||
.HasForeignKey(x => x.MakeupExamSessionId).OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne(x => x.Student).WithMany()
|
||||
.HasForeignKey(x => x.StudentId).OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(x => x.SourceGradeRecord).WithMany()
|
||||
.HasForeignKey(x => x.SourceGradeRecordId).OnDelete(DeleteBehavior.SetNull);
|
||||
entity.HasOne(x => x.SourceDeferredExam).WithMany()
|
||||
.HasForeignKey(x => x.SourceDeferredExamId).OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
builder.Entity<StudentStatusChange>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Reason).HasMaxLength(1000);
|
||||
|
||||
@@ -298,6 +298,14 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
TeachingEvaluationMigration,
|
||||
evaluationSetupsExist ? [] : TeachingEvaluationStatements,
|
||||
cancellationToken);
|
||||
|
||||
var makeupExamsExist = await db.Database
|
||||
.SqlQueryRaw<int>("SELECT COUNT(*) AS \"Value\" FROM sqlite_master WHERE type = 'table' AND name = 'MakeupExamPlans'")
|
||||
.AnyAsync(value => value > 0, cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
MakeupExamsMigration,
|
||||
makeupExamsExist ? [] : MakeupExamStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ApplyMigrationAsync(
|
||||
@@ -1651,4 +1659,20 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"""CREATE UNIQUE INDEX "IX_EvaluationRecords_SetupId_StudentId_TaskId" ON "EvaluationRecords" ("EvaluationSetupId", "StudentId", "TeachingTaskId");""",
|
||||
"""CREATE TABLE "EvaluationScores" ("EvaluationRecordId" TEXT NOT NULL, "EvaluationDimensionId" TEXT NOT NULL, "Score" INTEGER NOT NULL, CONSTRAINT "PK_EvaluationScores" PRIMARY KEY ("EvaluationRecordId", "EvaluationDimensionId"), CONSTRAINT "FK_EvaluationScores_EvaluationRecords_EvaluationRecordId" FOREIGN KEY ("EvaluationRecordId") REFERENCES "EvaluationRecords" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_EvaluationScores_EvaluationDimensions_EvaluationDimensionId" FOREIGN KEY ("EvaluationDimensionId") REFERENCES "EvaluationDimensions" ("Id") ON DELETE RESTRICT);""",
|
||||
];
|
||||
|
||||
private const string MakeupExamsMigration = "MakeupExams";
|
||||
|
||||
private static readonly string[] MakeupExamStatements =
|
||||
[
|
||||
"""CREATE TABLE "MakeupExamPlans" ("Id" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, "AcademicTermId" TEXT NOT NULL, "Name" TEXT NOT NULL, "Status" INTEGER NOT NULL, "Notes" TEXT NULL, "PublishedAt" TEXT NULL, CONSTRAINT "PK_MakeupExamPlans" PRIMARY KEY ("Id"), CONSTRAINT "FK_MakeupExamPlans_AcademicTerms_AcademicTermId" FOREIGN KEY ("AcademicTermId") REFERENCES "AcademicTerms" ("Id") ON DELETE RESTRICT);""",
|
||||
"""CREATE INDEX "IX_MakeupExamPlans_AcademicTermId_Status" ON "MakeupExamPlans" ("AcademicTermId", "Status");""",
|
||||
"""CREATE TABLE "MakeupExamSessions" ("Id" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, "MakeupExamPlanId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "ClassroomId" TEXT NULL, "ExamDate" TEXT NOT NULL, "StartPeriod" INTEGER NOT NULL, "PeriodCount" INTEGER NOT NULL, "StartsAt" TEXT NOT NULL, "EndsAt" TEXT NOT NULL, "RequiredBuildingId" TEXT NULL, "RequiredInvigilatorCount" INTEGER NOT NULL, "Notes" TEXT NULL, CONSTRAINT "PK_MakeupExamSessions" PRIMARY KEY ("Id"), CONSTRAINT "FK_MakeupExamSessions_MakeupExamPlans_MakeupExamPlanId" FOREIGN KEY ("MakeupExamPlanId") REFERENCES "MakeupExamPlans" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_MakeupExamSessions_TeachingTasks_TeachingTaskId" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_MakeupExamSessions_Classrooms_ClassroomId" FOREIGN KEY ("ClassroomId") REFERENCES "Classrooms" ("Id") ON DELETE SET NULL, CONSTRAINT "FK_MakeupExamSessions_Buildings_RequiredBuildingId" FOREIGN KEY ("RequiredBuildingId") REFERENCES "Buildings" ("Id") ON DELETE SET NULL);""",
|
||||
"""CREATE INDEX "IX_MakeupExamSessions_MakeupExamPlanId_StartsAt" ON "MakeupExamSessions" ("MakeupExamPlanId", "StartsAt");""",
|
||||
"""CREATE INDEX "IX_MakeupExamSessions_TeachingTaskId" ON "MakeupExamSessions" ("TeachingTaskId");""",
|
||||
"""CREATE INDEX "IX_MakeupExamSessions_MakeupExamPlanId_ExamDate" ON "MakeupExamSessions" ("MakeupExamPlanId", "ExamDate");""",
|
||||
"""CREATE INDEX "IX_MakeupExamSessions_RequiredBuildingId" ON "MakeupExamSessions" ("RequiredBuildingId");""",
|
||||
"""CREATE TABLE "MakeupExamSessionInvigilators" ("MakeupExamSessionId" TEXT NOT NULL, "TeacherId" TEXT NOT NULL, CONSTRAINT "PK_MakeupExamSessionInvigilators" PRIMARY KEY ("MakeupExamSessionId", "TeacherId"), CONSTRAINT "FK_MakeupExamSessionInvigilators_MakeupExamSessions_MakeupExamSessionId" FOREIGN KEY ("MakeupExamSessionId") REFERENCES "MakeupExamSessions" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_MakeupExamSessionInvigilators_Teachers_TeacherId" FOREIGN KEY ("TeacherId") REFERENCES "Teachers" ("Id") ON DELETE RESTRICT);""",
|
||||
"""CREATE TABLE "MakeupExamEnrollments" ("MakeupExamSessionId" TEXT NOT NULL, "StudentId" TEXT NOT NULL, "Reason" INTEGER NOT NULL, "SourceGradeRecordId" TEXT NULL, "SourceDeferredExamId" TEXT NULL, "MakeupScore" TEXT NULL, CONSTRAINT "PK_MakeupExamEnrollments" PRIMARY KEY ("MakeupExamSessionId", "StudentId"), CONSTRAINT "FK_MakeupExamEnrollments_MakeupExamSessions_MakeupExamSessionId" FOREIGN KEY ("MakeupExamSessionId") REFERENCES "MakeupExamSessions" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_MakeupExamEnrollments_Students_StudentId" FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_MakeupExamEnrollments_GradeRecords_SourceGradeRecordId" FOREIGN KEY ("SourceGradeRecordId") REFERENCES "GradeRecords" ("Id") ON DELETE SET NULL, CONSTRAINT "FK_MakeupExamEnrollments_DeferredExams_SourceDeferredExamId" FOREIGN KEY ("SourceDeferredExamId") REFERENCES "DeferredExams" ("Id") ON DELETE SET NULL);""",
|
||||
"""CREATE INDEX "IX_MakeupExamEnrollments_StudentId_MakeupExamSessionId" ON "MakeupExamEnrollments" ("StudentId", "MakeupExamSessionId");""",
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user