优化排课
This commit is contained in:
@@ -27,6 +27,8 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
public DbSet<TeachingTask> TeachingTasks => Set<TeachingTask>();
|
||||
public DbSet<TeachingTaskTeacher> TeachingTaskTeachers => Set<TeachingTaskTeacher>();
|
||||
public DbSet<TeachingTaskClass> TeachingTaskClasses => Set<TeachingTaskClass>();
|
||||
public DbSet<TeacherCourseApplication> TeacherCourseApplications =>
|
||||
Set<TeacherCourseApplication>();
|
||||
public DbSet<SchedulePlan> SchedulePlans => Set<SchedulePlan>();
|
||||
public DbSet<ScheduleEntry> ScheduleEntries => Set<ScheduleEntry>();
|
||||
public DbSet<ScheduleTimeSlot> ScheduleTimeSlots => Set<ScheduleTimeSlot>();
|
||||
@@ -229,6 +231,7 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
{
|
||||
entity.Property(x => x.TaskNumber).HasMaxLength(40);
|
||||
entity.Property(x => x.Name).HasMaxLength(120);
|
||||
entity.Property(x => x.GenerationBatchCode).HasMaxLength(40);
|
||||
entity.Property(x => x.Notes).HasMaxLength(500);
|
||||
entity.HasIndex(x => x.TaskNumber).IsUnique();
|
||||
entity.HasIndex(x => new { x.AcademicTermId, x.Status });
|
||||
@@ -268,6 +271,35 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
builder.Entity<TeacherCourseApplication>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Statement).HasMaxLength(500);
|
||||
entity.Property(x => x.ReviewComment).HasMaxLength(500);
|
||||
entity.HasIndex(x => new
|
||||
{
|
||||
x.AcademicTermId,
|
||||
x.TeacherId,
|
||||
x.CourseId
|
||||
}).IsUnique();
|
||||
entity.HasIndex(x => new { x.Status, x.AcademicTermId });
|
||||
entity.HasOne(x => x.AcademicTerm)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.AcademicTermId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne(x => x.Teacher)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.TeacherId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne(x => x.Course)
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.CourseId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne<ApplicationUser>()
|
||||
.WithMany()
|
||||
.HasForeignKey(x => x.ReviewedByUserId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
builder.Entity<SchedulePlan>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Name).HasMaxLength(120);
|
||||
|
||||
@@ -21,6 +21,8 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
private const string CourseCategoriesMigration = "20260724_13_course_categories";
|
||||
private const string SchedulingOptimizationMigration =
|
||||
"20260724_14_scheduling_optimization";
|
||||
private const string TeacherCourseApplicationsMigration =
|
||||
"20260724_15_teacher_course_applications";
|
||||
|
||||
public async Task MigrateAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -121,6 +123,18 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
SchedulingOptimizationMigration,
|
||||
schedulingOptimizationExists ? [] : SchedulingOptimizationStatements,
|
||||
cancellationToken);
|
||||
var teacherCourseApplicationsExist = await db.Database
|
||||
.SqlQueryRaw<int>(
|
||||
"""
|
||||
SELECT COUNT(*) AS "Value"
|
||||
FROM sqlite_master
|
||||
WHERE type = 'table' AND name = 'TeacherCourseApplications'
|
||||
""")
|
||||
.AnyAsync(value => value > 0, cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
TeacherCourseApplicationsMigration,
|
||||
teacherCourseApplicationsExist ? [] : TeacherCourseApplicationStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ApplyMigrationAsync(
|
||||
@@ -953,4 +967,59 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
ON "TeachingTaskAllowedClassrooms" ("ClassroomId");
|
||||
"""
|
||||
];
|
||||
|
||||
private static readonly string[] TeacherCourseApplicationStatements =
|
||||
[
|
||||
"""
|
||||
ALTER TABLE "TeachingTasks" ADD COLUMN "GenerationBatchCode" TEXT NULL;
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE "TeacherCourseApplications" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_TeacherCourseApplications" PRIMARY KEY,
|
||||
"AcademicTermId" TEXT NOT NULL,
|
||||
"TeacherId" TEXT NOT NULL,
|
||||
"CourseId" TEXT NOT NULL,
|
||||
"Status" INTEGER NOT NULL,
|
||||
"Statement" TEXT NULL,
|
||||
"ReviewComment" TEXT NULL,
|
||||
"SubmittedAt" TEXT NOT NULL,
|
||||
"ReviewedAt" TEXT NULL,
|
||||
"ReviewedByUserId" TEXT NULL,
|
||||
"CreatedAt" TEXT NOT NULL,
|
||||
"UpdatedAt" TEXT NOT NULL,
|
||||
CONSTRAINT "FK_TeacherCourseApplications_AcademicTerms"
|
||||
FOREIGN KEY ("AcademicTermId") REFERENCES "AcademicTerms" ("Id")
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT "FK_TeacherCourseApplications_Teachers"
|
||||
FOREIGN KEY ("TeacherId") REFERENCES "Teachers" ("Id")
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_TeacherCourseApplications_Courses"
|
||||
FOREIGN KEY ("CourseId") REFERENCES "Courses" ("Id")
|
||||
ON DELETE RESTRICT,
|
||||
CONSTRAINT "FK_TeacherCourseApplications_ReviewedBy"
|
||||
FOREIGN KEY ("ReviewedByUserId") REFERENCES "AspNetUsers" ("Id")
|
||||
ON DELETE SET NULL
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE UNIQUE INDEX "IX_TeacherCourseApplications_Term_Teacher_Course"
|
||||
ON "TeacherCourseApplications" ("AcademicTermId", "TeacherId", "CourseId");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX "IX_TeacherCourseApplications_Status_AcademicTermId"
|
||||
ON "TeacherCourseApplications" ("Status", "AcademicTermId");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX "IX_TeacherCourseApplications_TeacherId"
|
||||
ON "TeacherCourseApplications" ("TeacherId");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX "IX_TeacherCourseApplications_CourseId"
|
||||
ON "TeacherCourseApplications" ("CourseId");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX "IX_TeacherCourseApplications_ReviewedByUserId"
|
||||
ON "TeacherCourseApplications" ("ReviewedByUserId");
|
||||
"""
|
||||
];
|
||||
}
|
||||
|
||||
+2794
File diff suppressed because it is too large
Load Diff
+106
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class TeacherCourseApplications : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "GenerationBatchCode",
|
||||
table: "TeachingTasks",
|
||||
type: "varchar(40)",
|
||||
maxLength: 40,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TeacherCourseApplications",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
AcademicTermId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
TeacherId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
CourseId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
Status = table.Column<int>(type: "int", nullable: false),
|
||||
Statement = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
|
||||
ReviewComment = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
|
||||
SubmittedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
ReviewedAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
ReviewedByUserId = table.Column<Guid>(type: "char(36)", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TeacherCourseApplications", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeacherCourseApplications_AcademicTerms_AcademicTermId",
|
||||
column: x => x.AcademicTermId,
|
||||
principalTable: "AcademicTerms",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeacherCourseApplications_AspNetUsers_ReviewedByUserId",
|
||||
column: x => x.ReviewedByUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeacherCourseApplications_Courses_CourseId",
|
||||
column: x => x.CourseId,
|
||||
principalTable: "Courses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeacherCourseApplications_Teachers_TeacherId",
|
||||
column: x => x.TeacherId,
|
||||
principalTable: "Teachers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySQL:Charset", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeacherCourseApplications_AcademicTermId_TeacherId_CourseId",
|
||||
table: "TeacherCourseApplications",
|
||||
columns: new[] { "AcademicTermId", "TeacherId", "CourseId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeacherCourseApplications_CourseId",
|
||||
table: "TeacherCourseApplications",
|
||||
column: "CourseId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeacherCourseApplications_ReviewedByUserId",
|
||||
table: "TeacherCourseApplications",
|
||||
column: "ReviewedByUserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeacherCourseApplications_Status_AcademicTermId",
|
||||
table: "TeacherCourseApplications",
|
||||
columns: new[] { "Status", "AcademicTermId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeacherCourseApplications_TeacherId",
|
||||
table: "TeacherCourseApplications",
|
||||
column: "TeacherId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TeacherCourseApplications");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GenerationBatchCode",
|
||||
table: "TeachingTasks");
|
||||
}
|
||||
}
|
||||
}
|
||||
+93
@@ -1614,6 +1614,63 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.ToTable("Teachers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeacherCourseApplication", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("AcademicTermId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("CourseId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("ReviewComment")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("varchar(500)");
|
||||
|
||||
b.Property<DateTime?>("ReviewedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<Guid?>("ReviewedByUserId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Statement")
|
||||
.HasMaxLength(500)
|
||||
.HasColumnType("varchar(500)");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("SubmittedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<Guid>("TeacherId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CourseId");
|
||||
|
||||
b.HasIndex("ReviewedByUserId");
|
||||
|
||||
b.HasIndex("TeacherId");
|
||||
|
||||
b.HasIndex("Status", "AcademicTermId");
|
||||
|
||||
b.HasIndex("AcademicTermId", "TeacherId", "CourseId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("TeacherCourseApplications");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTask", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -1635,6 +1692,10 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Property<int>("EndWeek")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("GenerationBatchCode")
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("varchar(40)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(120)
|
||||
@@ -2464,6 +2525,38 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Navigation("College");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeacherCourseApplication", b =>
|
||||
{
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.AcademicTerm", "AcademicTerm")
|
||||
.WithMany()
|
||||
.HasForeignKey("AcademicTermId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.Course", "Course")
|
||||
.WithMany()
|
||||
.HasForeignKey("CourseId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Identity.ApplicationUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ReviewedByUserId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.Teacher", "Teacher")
|
||||
.WithMany()
|
||||
.HasForeignKey("TeacherId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AcademicTerm");
|
||||
|
||||
b.Navigation("Course");
|
||||
|
||||
b.Navigation("Teacher");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTask", b =>
|
||||
{
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.AcademicTerm", "AcademicTerm")
|
||||
|
||||
Reference in New Issue
Block a user