成绩+点名

This commit is contained in:
2026-07-25 14:08:50 +08:00 Unverified
parent 7800951aee
commit 36049af692
16 changed files with 1809 additions and 98 deletions
@@ -6,34 +6,45 @@ public static class GradeCalculator
{
public static bool AreWeightsValid(
decimal regularWeight,
decimal midtermWeight,
decimal finalWeight) =>
decimal finalWeight,
IEnumerable<GradeItem> items) =>
regularWeight is >= 0 and <= 100 &&
midtermWeight is >= 0 and <= 100 &&
finalWeight is >= 0 and <= 100 &&
regularWeight + midtermWeight + finalWeight == 100;
items.All(item => item.Weight is >= 0 and <= 100) &&
regularWeight + finalWeight + items.Sum(item => item.Weight) == 100;
public static decimal? CalculateTotal(
decimal? regularScore,
decimal? midtermScore,
decimal? finalScore,
IReadOnlyCollection<GradeItemScore> itemScores,
decimal regularWeight,
decimal midtermWeight,
decimal finalWeight,
IReadOnlyCollection<GradeItem> items,
GradeExamStatus examStatus)
{
if (examStatus != GradeExamStatus.Normal ||
regularWeight > 0 && !regularScore.HasValue ||
midtermWeight > 0 && !midtermScore.HasValue ||
finalWeight > 0 && !finalScore.HasValue)
{
if (examStatus != GradeExamStatus.Normal)
return null;
if (regularWeight > 0 && !regularScore.HasValue)
return null;
if (finalWeight > 0 && !finalScore.HasValue)
return null;
var itemWeightById = items.ToDictionary(item => item.Id, item => item.Weight);
foreach (var itemScore in itemScores)
{
if (itemWeightById.TryGetValue(itemScore.GradeItemId, out var weight) &&
weight > 0 && !itemScore.Score.HasValue)
return null;
}
var total =
(regularScore ?? 0) * regularWeight / 100 +
(midtermScore ?? 0) * midtermWeight / 100 +
(finalScore ?? 0) * finalWeight / 100;
var total = (regularScore ?? 0) * regularWeight / 100;
foreach (var itemScore in itemScores)
{
if (itemWeightById.TryGetValue(itemScore.GradeItemId, out var weight))
total += (itemScore.Score ?? 0) * weight / 100;
}
total += (finalScore ?? 0) * finalWeight / 100;
return Math.Round(total, 1, MidpointRounding.AwayFromZero);
}
@@ -47,6 +47,10 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
public DbSet<CourseEnrollment> CourseEnrollments => Set<CourseEnrollment>();
public DbSet<GradeSheet> GradeSheets => Set<GradeSheet>();
public DbSet<GradeRecord> GradeRecords => Set<GradeRecord>();
public DbSet<GradeItem> GradeItems => Set<GradeItem>();
public DbSet<GradeItemScore> GradeItemScores => Set<GradeItemScore>();
public DbSet<AttendanceSheet> AttendanceSheets => Set<AttendanceSheet>();
public DbSet<AttendanceRecord> AttendanceRecords => Set<AttendanceRecord>();
public DbSet<ExamPlan> ExamPlans => Set<ExamPlan>();
public DbSet<ExamSession> ExamSessions => Set<ExamSession>();
public DbSet<ExamSessionInvigilator> ExamSessionInvigilators =>
@@ -468,7 +472,6 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
builder.Entity<GradeSheet>(entity =>
{
entity.Property(x => x.RegularWeight).HasPrecision(5, 1);
entity.Property(x => x.MidtermWeight).HasPrecision(5, 1);
entity.Property(x => x.FinalWeight).HasPrecision(5, 1);
entity.Property(x => x.ReviewComment).HasMaxLength(500);
entity.HasIndex(x => x.TeachingTaskId).IsUnique();
@@ -479,10 +482,20 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<GradeItem>(entity =>
{
entity.Property(x => x.Name).HasMaxLength(60);
entity.Property(x => x.Weight).HasPrecision(5, 1);
entity.HasIndex(x => new { x.GradeSheetId, x.SortOrder });
entity.HasOne(x => x.GradeSheet)
.WithMany(x => x.Items)
.HasForeignKey(x => x.GradeSheetId)
.OnDelete(DeleteBehavior.Cascade);
});
builder.Entity<GradeRecord>(entity =>
{
entity.Property(x => x.RegularScore).HasPrecision(5, 1);
entity.Property(x => x.MidtermScore).HasPrecision(5, 1);
entity.Property(x => x.FinalScore).HasPrecision(5, 1);
entity.Property(x => x.TotalScore).HasPrecision(5, 1);
entity.Property(x => x.GradePoint).HasPrecision(3, 1);
@@ -499,6 +512,45 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<GradeItemScore>(entity =>
{
entity.HasKey(x => new { x.GradeRecordId, x.GradeItemId });
entity.Property(x => x.Score).HasPrecision(5, 1);
entity.HasOne(x => x.GradeRecord)
.WithMany(x => x.ItemScores)
.HasForeignKey(x => x.GradeRecordId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne(x => x.GradeItem)
.WithMany(x => x.Scores)
.HasForeignKey(x => x.GradeItemId)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<AttendanceSheet>(entity =>
{
entity.Property(x => x.Name).HasMaxLength(120);
entity.Property(x => x.Notes).HasMaxLength(500);
entity.HasIndex(x => new { x.TeachingTaskId, x.AttendanceDate });
entity.HasOne(x => x.TeachingTask)
.WithMany()
.HasForeignKey(x => x.TeachingTaskId)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<AttendanceRecord>(entity =>
{
entity.HasKey(x => new { x.AttendanceSheetId, x.StudentId });
entity.Property(x => x.Notes).HasMaxLength(300);
entity.HasOne(x => x.AttendanceSheet)
.WithMany(x => x.Records)
.HasForeignKey(x => x.AttendanceSheetId)
.OnDelete(DeleteBehavior.Cascade);
entity.HasOne(x => x.Student)
.WithMany()
.HasForeignKey(x => x.StudentId)
.OnDelete(DeleteBehavior.Restrict);
});
builder.Entity<ExamPlan>(entity =>
{
entity.Property(x => x.Name).HasMaxLength(120);
@@ -546,7 +546,6 @@ public sealed class DatabaseInitializer(
{
TeachingTaskId = task.Id,
RegularWeight = 30,
MidtermWeight = 0,
FinalWeight = 70,
Status = GradeSheetStatus.Draft,
Records =
@@ -14,6 +14,7 @@ public sealed class DevelopmentSqliteMigrator(
private const string CourseSelectionMigration = "20260724_06_course_selection";
private const string GradesMigration = "20260724_07_grades";
private const string ExamsMigration = "20260724_08_exams";
private const string AttendanceMigration = "20260724_08b_attendance";
private const string StudentStatusChangesMigration = "20260724_09_student_status_changes";
private const string GraduationAuditsMigration = "20260724_10_graduation_audits";
private const string DegreeAwardsMigration = "20260724_11_degree_awards";
@@ -29,6 +30,8 @@ public sealed class DevelopmentSqliteMigrator(
"20260725_17_teaching_task_scheduling_modes";
private const string SchedulePublishJobsMigration =
"20260725_18_schedule_publish_jobs";
private const string FlexibleGradesMigration =
"20260725_19_flexible_grades";
public async Task MigrateAsync(CancellationToken cancellationToken = default)
{
@@ -177,6 +180,34 @@ public sealed class DevelopmentSqliteMigrator(
SchedulePublishJobsMigration,
schedulePublishJobsExist ? [] : SchedulePublishJobStatements,
cancellationToken);
var midtermWeightExists = await db.Database
.SqlQueryRaw<int>(
"""
SELECT COUNT(*) AS "Value"
FROM pragma_table_info('GradeSheets')
WHERE name = 'MidtermWeight'
""")
.AnyAsync(value => value > 0, cancellationToken);
await ApplyMigrationAsync(
FlexibleGradesMigration,
midtermWeightExists
? FlexibleGradesUpgradeStatements
: FlexibleGradesNewStatements,
cancellationToken);
var attendanceSheetsExist = await db.Database
.SqlQueryRaw<int>(
"""
SELECT COUNT(*) AS "Value"
FROM sqlite_master
WHERE type = 'table' AND name = 'AttendanceSheets'
""")
.AnyAsync(value => value > 0, cancellationToken);
await ApplyMigrationAsync(
AttendanceMigration,
attendanceSheetsExist ? [] : AttendanceStatements,
cancellationToken);
}
private async Task ApplyMigrationAsync(
@@ -629,7 +660,6 @@ public sealed class DevelopmentSqliteMigrator(
"Id" TEXT NOT NULL CONSTRAINT "PK_GradeSheets" PRIMARY KEY,
"TeachingTaskId" TEXT NOT NULL,
"RegularWeight" TEXT NOT NULL,
"MidtermWeight" TEXT NOT NULL,
"FinalWeight" TEXT NOT NULL,
"Status" INTEGER NOT NULL,
"ReviewComment" TEXT NULL,
@@ -656,7 +686,6 @@ public sealed class DevelopmentSqliteMigrator(
"GradeSheetId" TEXT NOT NULL,
"StudentId" TEXT NOT NULL,
"RegularScore" TEXT NULL,
"MidtermScore" TEXT NULL,
"FinalScore" TEXT NULL,
"TotalScore" TEXT NULL,
"GradePoint" TEXT NULL,
@@ -723,6 +752,182 @@ public sealed class DevelopmentSqliteMigrator(
"""CREATE INDEX IF NOT EXISTS "IX_ExamSessionInvigilators_TeacherId" ON "ExamSessionInvigilators" ("TeacherId");"""
];
private static readonly string[] FlexibleGradesNewStatements =
[
"""
CREATE TABLE IF NOT EXISTS "GradeItems" (
"Id" TEXT NOT NULL CONSTRAINT "PK_GradeItems" PRIMARY KEY,
"GradeSheetId" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"Weight" TEXT NOT NULL,
"SortOrder" INTEGER NOT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_GradeItems_GradeSheets_GradeSheetId"
FOREIGN KEY ("GradeSheetId") REFERENCES "GradeSheets" ("Id") ON DELETE CASCADE
);
""",
"""
CREATE INDEX IF NOT EXISTS "IX_GradeItems_GradeSheetId_SortOrder"
ON "GradeItems" ("GradeSheetId", "SortOrder");
""",
"""
CREATE TABLE IF NOT EXISTS "GradeItemScores" (
"GradeRecordId" TEXT NOT NULL,
"GradeItemId" TEXT NOT NULL,
"Score" TEXT NULL,
CONSTRAINT "PK_GradeItemScores" PRIMARY KEY ("GradeRecordId", "GradeItemId"),
CONSTRAINT "FK_GradeItemScores_GradeRecords_GradeRecordId"
FOREIGN KEY ("GradeRecordId") REFERENCES "GradeRecords" ("Id") ON DELETE CASCADE,
CONSTRAINT "FK_GradeItemScores_GradeItems_GradeItemId"
FOREIGN KEY ("GradeItemId") REFERENCES "GradeItems" ("Id") ON DELETE RESTRICT
);
"""
];
private static readonly string[] FlexibleGradesUpgradeStatements =
[
"""
CREATE TABLE "GradeSheets_v2" (
"Id" TEXT NOT NULL CONSTRAINT "PK_GradeSheets" PRIMARY KEY,
"TeachingTaskId" TEXT NOT NULL,
"RegularWeight" TEXT NOT NULL,
"FinalWeight" TEXT NOT NULL,
"Status" INTEGER NOT NULL,
"ReviewComment" TEXT NULL,
"SubmittedAt" TEXT NULL,
"ReviewedAt" TEXT NULL,
"PublishedAt" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_GradeSheets_TeachingTasks_TeachingTaskId"
FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT
);
""",
"""
INSERT INTO "GradeSheets_v2" ("Id","TeachingTaskId","RegularWeight","FinalWeight",
"Status","ReviewComment","SubmittedAt","ReviewedAt","PublishedAt","CreatedAt","UpdatedAt")
SELECT "Id","TeachingTaskId","RegularWeight","FinalWeight",
"Status","ReviewComment","SubmittedAt","ReviewedAt","PublishedAt","CreatedAt","UpdatedAt"
FROM "GradeSheets";
""",
"DROP TABLE \"GradeSheets\";",
"ALTER TABLE \"GradeSheets_v2\" RENAME TO \"GradeSheets\";",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_GradeSheets_TeachingTaskId"
ON "GradeSheets" ("TeachingTaskId");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_GradeSheets_Status"
ON "GradeSheets" ("Status");
""",
"""
CREATE TABLE "GradeRecords_v2" (
"Id" TEXT NOT NULL CONSTRAINT "PK_GradeRecords" PRIMARY KEY,
"GradeSheetId" TEXT NOT NULL,
"StudentId" TEXT NOT NULL,
"RegularScore" TEXT NULL,
"FinalScore" TEXT NULL,
"TotalScore" TEXT NULL,
"GradePoint" TEXT NULL,
"ExamStatus" INTEGER NOT NULL,
"Notes" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_GradeRecords_GradeSheets_GradeSheetId"
FOREIGN KEY ("GradeSheetId") REFERENCES "GradeSheets" ("Id") ON DELETE CASCADE,
CONSTRAINT "FK_GradeRecords_Students_StudentId"
FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT
);
""",
"""
INSERT INTO "GradeRecords_v2" ("Id","GradeSheetId","StudentId","RegularScore","FinalScore",
"TotalScore","GradePoint","ExamStatus","Notes","CreatedAt","UpdatedAt")
SELECT "Id","GradeSheetId","StudentId","RegularScore","FinalScore",
"TotalScore","GradePoint","ExamStatus","Notes","CreatedAt","UpdatedAt"
FROM "GradeRecords";
""",
"DROP TABLE \"GradeRecords\";",
"ALTER TABLE \"GradeRecords_v2\" RENAME TO \"GradeRecords\";",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_GradeRecords_GradeSheetId_StudentId"
ON "GradeRecords" ("GradeSheetId", "StudentId");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_GradeRecords_StudentId_TotalScore"
ON "GradeRecords" ("StudentId", "TotalScore");
""",
"""
CREATE TABLE IF NOT EXISTS "GradeItems" (
"Id" TEXT NOT NULL CONSTRAINT "PK_GradeItems" PRIMARY KEY,
"GradeSheetId" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"Weight" TEXT NOT NULL,
"SortOrder" INTEGER NOT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_GradeItems_GradeSheets_GradeSheetId"
FOREIGN KEY ("GradeSheetId") REFERENCES "GradeSheets" ("Id") ON DELETE CASCADE
);
""",
"""
CREATE INDEX IF NOT EXISTS "IX_GradeItems_GradeSheetId_SortOrder"
ON "GradeItems" ("GradeSheetId", "SortOrder");
""",
"""
CREATE TABLE IF NOT EXISTS "GradeItemScores" (
"GradeRecordId" TEXT NOT NULL,
"GradeItemId" TEXT NOT NULL,
"Score" TEXT NULL,
CONSTRAINT "PK_GradeItemScores" PRIMARY KEY ("GradeRecordId", "GradeItemId"),
CONSTRAINT "FK_GradeItemScores_GradeRecords_GradeRecordId"
FOREIGN KEY ("GradeRecordId") REFERENCES "GradeRecords" ("Id") ON DELETE CASCADE,
CONSTRAINT "FK_GradeItemScores_GradeItems_GradeItemId"
FOREIGN KEY ("GradeItemId") REFERENCES "GradeItems" ("Id") ON DELETE RESTRICT
);
"""
];
private static readonly string[] AttendanceStatements =
[
"""
CREATE TABLE IF NOT EXISTS "AttendanceSheets" (
"Id" TEXT NOT NULL CONSTRAINT "PK_AttendanceSheets" PRIMARY KEY,
"TeachingTaskId" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"AttendanceDate" TEXT NOT NULL,
"Status" INTEGER NOT NULL,
"Notes" TEXT NULL,
"SubmittedAt" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_AttendanceSheets_TeachingTasks_TeachingTaskId"
FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT
);
""",
"""
CREATE INDEX IF NOT EXISTS "IX_AttendanceSheets_TeachingTaskId_AttendanceDate"
ON "AttendanceSheets" ("TeachingTaskId", "AttendanceDate");
""",
"""
CREATE TABLE IF NOT EXISTS "AttendanceRecords" (
"AttendanceSheetId" TEXT NOT NULL,
"StudentId" TEXT NOT NULL,
"Status" INTEGER NOT NULL,
"Notes" TEXT NULL,
CONSTRAINT "PK_AttendanceRecords" PRIMARY KEY ("AttendanceSheetId", "StudentId"),
CONSTRAINT "FK_AttendanceRecords_AttendanceSheets_AttendanceSheetId"
FOREIGN KEY ("AttendanceSheetId") REFERENCES "AttendanceSheets" ("Id") ON DELETE CASCADE,
CONSTRAINT "FK_AttendanceRecords_Students_StudentId"
FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT
);
""",
"""
CREATE INDEX IF NOT EXISTS "IX_AttendanceRecords_AttendanceSheetId_StudentId"
ON "AttendanceRecords" ("AttendanceSheetId", "StudentId");
"""
];
private static readonly string[] StudentStatusChangesStatements =
[
"""
@@ -0,0 +1,184 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
{
/// <inheritdoc />
public partial class FlexibleGradesAndAttendance : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "GradeItems",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
GradeSheetId = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "varchar(60)", maxLength: 60, nullable: false),
Weight = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
SortOrder = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GradeItems", x => x.Id);
table.ForeignKey(
name: "FK_GradeItems_GradeSheets_GradeSheetId",
column: x => x.GradeSheetId,
principalTable: "GradeSheets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "GradeItemScores",
columns: table => new
{
GradeRecordId = table.Column<Guid>(type: "char(36)", nullable: false),
GradeItemId = table.Column<Guid>(type: "char(36)", nullable: false),
Score = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_GradeItemScores", x => new { x.GradeRecordId, x.GradeItemId });
table.ForeignKey(
name: "FK_GradeItemScores_GradeItems_GradeItemId",
column: x => x.GradeItemId,
principalTable: "GradeItems",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_GradeItemScores_GradeRecords_GradeRecordId",
column: x => x.GradeRecordId,
principalTable: "GradeRecords",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_GradeItems_GradeSheetId_SortOrder",
table: "GradeItems",
columns: new[] { "GradeSheetId", "SortOrder" });
migrationBuilder.CreateIndex(
name: "IX_GradeItemScores_GradeRecordId_GradeItemId",
table: "GradeItemScores",
columns: new[] { "GradeRecordId", "GradeItemId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_GradeItemScores_GradeItemId",
table: "GradeItemScores",
column: "GradeItemId");
migrationBuilder.DropColumn(
name: "MidtermWeight",
table: "GradeSheets");
migrationBuilder.DropColumn(
name: "MidtermScore",
table: "GradeRecords");
migrationBuilder.CreateTable(
name: "AttendanceSheets",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false),
TeachingTaskId = table.Column<Guid>(type: "char(36)", nullable: false),
Name = table.Column<string>(type: "varchar(120)", maxLength: 120, nullable: false),
AttendanceDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
Status = table.Column<int>(type: "int", nullable: false),
Notes = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
SubmittedAt = table.Column<DateTime>(type: "datetime(6)", 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_AttendanceSheets", x => x.Id);
table.ForeignKey(
name: "FK_AttendanceSheets_TeachingTasks_TeachingTaskId",
column: x => x.TeachingTaskId,
principalTable: "TeachingTasks",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateTable(
name: "AttendanceRecords",
columns: table => new
{
AttendanceSheetId = table.Column<Guid>(type: "char(36)", nullable: false),
StudentId = table.Column<Guid>(type: "char(36)", nullable: false),
Status = table.Column<int>(type: "int", nullable: false),
Notes = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AttendanceRecords", x => new { x.AttendanceSheetId, x.StudentId });
table.ForeignKey(
name: "FK_AttendanceRecords_AttendanceSheets_AttendanceSheetId",
column: x => x.AttendanceSheetId,
principalTable: "AttendanceSheets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AttendanceRecords_Students_StudentId",
column: x => x.StudentId,
principalTable: "Students",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
})
.Annotation("MySQL:Charset", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_AttendanceSheets_TeachingTaskId_AttendanceDate",
table: "AttendanceSheets",
columns: new[] { "TeachingTaskId", "AttendanceDate" });
migrationBuilder.CreateIndex(
name: "IX_AttendanceRecords_AttendanceSheetId_StudentId",
table: "AttendanceRecords",
columns: new[] { "AttendanceSheetId", "StudentId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AttendanceRecords_StudentId",
table: "AttendanceRecords",
column: "StudentId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(name: "AttendanceRecords");
migrationBuilder.DropTable(name: "AttendanceSheets");
migrationBuilder.DropTable(name: "GradeItemScores");
migrationBuilder.DropTable(name: "GradeItems");
migrationBuilder.AddColumn<decimal>(
name: "MidtermWeight",
table: "GradeSheets",
type: "decimal(5,1)",
precision: 5,
scale: 1,
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<decimal>(
name: "MidtermScore",
table: "GradeRecords",
type: "decimal(5,1)",
precision: 5,
scale: 1,
nullable: true);
}
}
}