教师成绩报告
This commit is contained in:
@@ -185,6 +185,9 @@ public static class AppCacheKeys
|
||||
|
||||
public static string CourseGradeStatistics(Guid gradeSheetId) =>
|
||||
$"grade-statistics:sheet:{gradeSheetId:N}";
|
||||
|
||||
public static string TeachingTaskGradeAnalytics(Guid gradeSheetId) =>
|
||||
$"grade-analytics:sheet:{gradeSheetId:N}:v1";
|
||||
}
|
||||
|
||||
public static class AppCacheTags
|
||||
|
||||
@@ -49,6 +49,8 @@ public sealed class CourseGradeStatisticsRefreshJobProcessor(
|
||||
x.GradeSheet.TeachingTask!.CourseId == target.CourseId &&
|
||||
x.GradeSheet.TeachingTask.AcademicTermId == target.AcademicTermId)
|
||||
.Select(x => new ScoreRow(
|
||||
x.GradeSheetId,
|
||||
x.GradeSheet!.TeachingTaskId,
|
||||
x.TotalScore!.Value,
|
||||
x.Student!.AdministrativeClassId,
|
||||
x.Student.AdministrativeClass!.MajorId,
|
||||
@@ -65,6 +67,16 @@ public sealed class CourseGradeStatisticsRefreshJobProcessor(
|
||||
scores.GroupBy(x => x.CollegeId), rebuilt, target, now);
|
||||
AddUniversityStatistic(scores, rebuilt, target, now);
|
||||
|
||||
var rebuiltTeachingTasks = scores
|
||||
.GroupBy(x => new { x.GradeSheetId, x.TeachingTaskId })
|
||||
.Select(group => CreateTeachingTaskStatistic(
|
||||
group.Key.GradeSheetId,
|
||||
group.Key.TeachingTaskId,
|
||||
group.Select(x => x.Score),
|
||||
target,
|
||||
now))
|
||||
.ToList();
|
||||
|
||||
await db.CourseGradeStatistics
|
||||
.Where(x => x.CourseId == target.CourseId &&
|
||||
x.AcademicTermId == target.AcademicTermId)
|
||||
@@ -72,6 +84,24 @@ public sealed class CourseGradeStatisticsRefreshJobProcessor(
|
||||
if (rebuilt.Count > 0)
|
||||
db.CourseGradeStatistics.AddRange(rebuilt);
|
||||
|
||||
var oldTeachingTaskStatisticIds = await db.TeachingTaskGradeStatistics
|
||||
.Where(x => x.CourseId == target.CourseId &&
|
||||
x.AcademicTermId == target.AcademicTermId)
|
||||
.Select(x => x.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
if (oldTeachingTaskStatisticIds.Count > 0)
|
||||
{
|
||||
await db.TeachingTaskGradeScoreBands
|
||||
.Where(x => oldTeachingTaskStatisticIds.Contains(
|
||||
x.TeachingTaskGradeStatisticId))
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
await db.TeachingTaskGradeStatistics
|
||||
.Where(x => oldTeachingTaskStatisticIds.Contains(x.Id))
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
}
|
||||
if (rebuiltTeachingTasks.Count > 0)
|
||||
db.TeachingTaskGradeStatistics.AddRange(rebuiltTeachingTasks);
|
||||
|
||||
job.Status = CourseGradeStatisticsRefreshJobStatus.Succeeded;
|
||||
job.CompletedAt = now;
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
@@ -141,6 +171,80 @@ public sealed class CourseGradeStatisticsRefreshJobProcessor(
|
||||
};
|
||||
}
|
||||
|
||||
private sealed record ScoreRow(decimal Score, Guid ClassId, Guid MajorId, Guid CollegeId);
|
||||
private static TeachingTaskGradeStatistic CreateTeachingTaskStatistic(
|
||||
Guid gradeSheetId,
|
||||
Guid teachingTaskId,
|
||||
IEnumerable<decimal> source,
|
||||
StatisticsTarget targetInfo,
|
||||
DateTime calculatedAt)
|
||||
{
|
||||
var scores = source.OrderBy(x => x).ToArray();
|
||||
var passed = scores.Count(x => x >= 60m);
|
||||
var excellent = scores.Count(x => x >= 90m);
|
||||
var average = scores.Average();
|
||||
var middle = scores.Length / 2;
|
||||
var median = scores.Length % 2 == 0
|
||||
? (scores[middle - 1] + scores[middle]) / 2m
|
||||
: scores[middle];
|
||||
var variance = scores.Average(x =>
|
||||
(double)((x - average) * (x - average)));
|
||||
|
||||
var statistic = new TeachingTaskGradeStatistic
|
||||
{
|
||||
GradeSheetId = gradeSheetId,
|
||||
TeachingTaskId = teachingTaskId,
|
||||
CourseId = targetInfo.CourseId,
|
||||
AcademicTermId = targetInfo.AcademicTermId,
|
||||
StudentCount = scores.Length,
|
||||
PassedCount = passed,
|
||||
ExcellentCount = excellent,
|
||||
HighestScore = scores.Max(),
|
||||
AverageScore = Math.Round(average, 1),
|
||||
MedianScore = Math.Round(median, 1),
|
||||
LowestScore = scores.Min(),
|
||||
StandardDeviation = Math.Round((decimal)Math.Sqrt(variance), 2),
|
||||
PassRate = Math.Round((decimal)passed / scores.Length * 100m, 2),
|
||||
ExcellentRate = Math.Round((decimal)excellent / scores.Length * 100m, 2),
|
||||
CalculatedAt = calculatedAt
|
||||
};
|
||||
statistic.ScoreBands =
|
||||
[
|
||||
CreateBand(statistic.Id, "0–59", 0m, 60m,
|
||||
scores.Count(x => x < 60m), 0),
|
||||
CreateBand(statistic.Id, "60–69", 60m, 70m,
|
||||
scores.Count(x => x >= 60m && x < 70m), 1),
|
||||
CreateBand(statistic.Id, "70–79", 70m, 80m,
|
||||
scores.Count(x => x >= 70m && x < 80m), 2),
|
||||
CreateBand(statistic.Id, "80–89", 80m, 90m,
|
||||
scores.Count(x => x >= 80m && x < 90m), 3),
|
||||
CreateBand(statistic.Id, "90–100", 90m, null,
|
||||
scores.Count(x => x >= 90m), 4)
|
||||
];
|
||||
return statistic;
|
||||
}
|
||||
|
||||
private static TeachingTaskGradeScoreBand CreateBand(
|
||||
Guid statisticId,
|
||||
string label,
|
||||
decimal lowerBound,
|
||||
decimal? upperBound,
|
||||
int count,
|
||||
int sortOrder) => new()
|
||||
{
|
||||
TeachingTaskGradeStatisticId = statisticId,
|
||||
Label = label,
|
||||
LowerBound = lowerBound,
|
||||
UpperBound = upperBound,
|
||||
StudentCount = count,
|
||||
SortOrder = sortOrder
|
||||
};
|
||||
|
||||
private sealed record ScoreRow(
|
||||
Guid GradeSheetId,
|
||||
Guid TeachingTaskId,
|
||||
decimal Score,
|
||||
Guid ClassId,
|
||||
Guid MajorId,
|
||||
Guid CollegeId);
|
||||
private sealed record StatisticsTarget(Guid CourseId, Guid AcademicTermId);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,10 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
public DbSet<GradeItemScore> GradeItemScores => Set<GradeItemScore>();
|
||||
public DbSet<CourseGradeStatistic> CourseGradeStatistics =>
|
||||
Set<CourseGradeStatistic>();
|
||||
public DbSet<TeachingTaskGradeStatistic> TeachingTaskGradeStatistics =>
|
||||
Set<TeachingTaskGradeStatistic>();
|
||||
public DbSet<TeachingTaskGradeScoreBand> TeachingTaskGradeScoreBands =>
|
||||
Set<TeachingTaskGradeScoreBand>();
|
||||
public DbSet<CourseGradeStatisticsRefreshJob> CourseGradeStatisticsRefreshJobs =>
|
||||
Set<CourseGradeStatisticsRefreshJob>();
|
||||
public DbSet<OtherExamBatch> OtherExamBatches => Set<OtherExamBatch>();
|
||||
@@ -868,6 +872,46 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
builder.Entity<TeachingTaskGradeStatistic>(entity =>
|
||||
{
|
||||
entity.Property(x => x.HighestScore).HasPrecision(5, 1);
|
||||
entity.Property(x => x.AverageScore).HasPrecision(5, 1);
|
||||
entity.Property(x => x.MedianScore).HasPrecision(5, 1);
|
||||
entity.Property(x => x.LowestScore).HasPrecision(5, 1);
|
||||
entity.Property(x => x.StandardDeviation).HasPrecision(6, 2);
|
||||
entity.Property(x => x.PassRate).HasPrecision(5, 2);
|
||||
entity.Property(x => x.ExcellentRate).HasPrecision(5, 2);
|
||||
entity.HasIndex(x => x.GradeSheetId).IsUnique();
|
||||
entity.HasIndex(x => x.TeachingTaskId).IsUnique();
|
||||
entity.HasIndex(x => new { x.CourseId, x.AcademicTermId });
|
||||
entity.HasOne(x => x.GradeSheet).WithOne()
|
||||
.HasForeignKey<TeachingTaskGradeStatistic>(x => x.GradeSheetId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne(x => x.TeachingTask).WithOne()
|
||||
.HasForeignKey<TeachingTaskGradeStatistic>(x => x.TeachingTaskId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
entity.HasOne<Course>().WithMany().HasForeignKey(x => x.CourseId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
entity.HasOne<AcademicTerm>().WithMany().HasForeignKey(x => x.AcademicTermId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
builder.Entity<TeachingTaskGradeScoreBand>(entity =>
|
||||
{
|
||||
entity.Property(x => x.Label).HasMaxLength(30);
|
||||
entity.Property(x => x.LowerBound).HasPrecision(5, 1);
|
||||
entity.Property(x => x.UpperBound).HasPrecision(5, 1);
|
||||
entity.HasIndex(x => new
|
||||
{
|
||||
x.TeachingTaskGradeStatisticId,
|
||||
x.SortOrder
|
||||
}).IsUnique();
|
||||
entity.HasOne(x => x.TeachingTaskGradeStatistic)
|
||||
.WithMany(x => x.ScoreBands)
|
||||
.HasForeignKey(x => x.TeachingTaskGradeStatisticId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
builder.Entity<CourseGradeStatisticsRefreshJob>(entity =>
|
||||
{
|
||||
entity.Property(x => x.ErrorMessage).HasMaxLength(2000);
|
||||
|
||||
@@ -88,6 +88,8 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"20260808_46_course_grade_statistics";
|
||||
private const string CourseGradeDistributionMigration =
|
||||
"20260809_47_course_grade_distribution";
|
||||
private const string TeachingTaskGradeAnalyticsMigration =
|
||||
"20260809_48_teaching_task_grade_analytics";
|
||||
|
||||
public async Task MigrateAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -647,9 +649,25 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
CourseGradeStatisticsMigration,
|
||||
CourseGradeStatisticsStatements,
|
||||
cancellationToken);
|
||||
var courseGradeStatisticColumns = (await db.Database
|
||||
.SqlQueryRaw<string>(
|
||||
"""
|
||||
SELECT name AS "Value"
|
||||
FROM pragma_table_info('CourseGradeStatistics')
|
||||
""")
|
||||
.ToListAsync(cancellationToken))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var missingDistributionStatements = CourseGradeDistributionColumns
|
||||
.Select((column, index) => new { column, index })
|
||||
.Where(x => !courseGradeStatisticColumns.Contains(x.column))
|
||||
.Select(x => CourseGradeDistributionStatements[x.index]);
|
||||
await ApplyMigrationAsync(
|
||||
CourseGradeDistributionMigration,
|
||||
CourseGradeDistributionStatements,
|
||||
missingDistributionStatements,
|
||||
cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
TeachingTaskGradeAnalyticsMigration,
|
||||
TeachingTaskGradeAnalyticsStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -2241,6 +2259,26 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
"""ALTER TABLE "CourseGradeStatistics" ADD COLUMN "From90To100Count" INTEGER NOT NULL DEFAULT 0;"""
|
||||
];
|
||||
|
||||
private static readonly string[] CourseGradeDistributionColumns =
|
||||
[
|
||||
"Below60Count",
|
||||
"From60To69Count",
|
||||
"From70To79Count",
|
||||
"From80To89Count",
|
||||
"From90To100Count"
|
||||
];
|
||||
|
||||
private static readonly string[] TeachingTaskGradeAnalyticsStatements =
|
||||
[
|
||||
"""CREATE TABLE IF NOT EXISTS "TeachingTaskGradeStatistics" ("Id" TEXT NOT NULL CONSTRAINT "PK_TeachingTaskGradeStatistics" PRIMARY KEY, "GradeSheetId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "CourseId" TEXT NOT NULL, "AcademicTermId" TEXT NOT NULL, "StudentCount" INTEGER NOT NULL, "PassedCount" INTEGER NOT NULL, "ExcellentCount" INTEGER NOT NULL, "HighestScore" TEXT NOT NULL, "AverageScore" TEXT NOT NULL, "MedianScore" TEXT NOT NULL, "LowestScore" TEXT NOT NULL, "StandardDeviation" TEXT NOT NULL, "PassRate" TEXT NOT NULL, "ExcellentRate" TEXT NOT NULL, "CalculatedAt" TEXT NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, CONSTRAINT "FK_TeachingTaskGradeStatistics_GradeSheets" FOREIGN KEY ("GradeSheetId") REFERENCES "GradeSheets" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_TeachingTaskGradeStatistics_TeachingTasks" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE CASCADE, CONSTRAINT "FK_TeachingTaskGradeStatistics_Courses" FOREIGN KEY ("CourseId") REFERENCES "Courses" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_TeachingTaskGradeStatistics_AcademicTerms" FOREIGN KEY ("AcademicTermId") REFERENCES "AcademicTerms" ("Id") ON DELETE RESTRICT);""",
|
||||
"""CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeachingTaskGradeStatistics_GradeSheetId" ON "TeachingTaskGradeStatistics" ("GradeSheetId");""",
|
||||
"""CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeachingTaskGradeStatistics_TeachingTaskId" ON "TeachingTaskGradeStatistics" ("TeachingTaskId");""",
|
||||
"""CREATE INDEX IF NOT EXISTS "IX_TeachingTaskGradeStatistics_CourseId_AcademicTermId" ON "TeachingTaskGradeStatistics" ("CourseId", "AcademicTermId");""",
|
||||
"""CREATE INDEX IF NOT EXISTS "IX_TeachingTaskGradeStatistics_AcademicTermId" ON "TeachingTaskGradeStatistics" ("AcademicTermId");""",
|
||||
"""CREATE TABLE IF NOT EXISTS "TeachingTaskGradeScoreBands" ("Id" TEXT NOT NULL CONSTRAINT "PK_TeachingTaskGradeScoreBands" PRIMARY KEY, "TeachingTaskGradeStatisticId" TEXT NOT NULL, "Label" TEXT NOT NULL, "LowerBound" TEXT NOT NULL, "UpperBound" TEXT NULL, "StudentCount" INTEGER NOT NULL, "SortOrder" INTEGER NOT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, CONSTRAINT "FK_TeachingTaskGradeScoreBands_Statistics" FOREIGN KEY ("TeachingTaskGradeStatisticId") REFERENCES "TeachingTaskGradeStatistics" ("Id") ON DELETE CASCADE);""",
|
||||
"""CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeachingTaskGradeScoreBands_StatisticId_SortOrder" ON "TeachingTaskGradeScoreBands" ("TeachingTaskGradeStatisticId", "SortOrder");"""
|
||||
];
|
||||
|
||||
private static readonly string[] ApprovalTableStatements =
|
||||
[
|
||||
"""CREATE TABLE "CourseExemptions" ("Id" TEXT NOT NULL CONSTRAINT "PK_CourseExemptions" PRIMARY KEY, "StudentId" TEXT NOT NULL, "TeachingTaskId" TEXT NOT NULL, "Reason" TEXT NOT NULL, "Status" INTEGER NOT NULL, "ReviewComment" TEXT NULL, "SubmittedAt" TEXT NOT NULL, "ReviewedAt" TEXT NULL, "ReviewedByUserId" TEXT NULL, "CreatedAt" TEXT NOT NULL, "UpdatedAt" TEXT NOT NULL, CONSTRAINT "FK_CourseExemptions_Students" FOREIGN KEY ("StudentId") REFERENCES "Students" ("Id") ON DELETE RESTRICT, CONSTRAINT "FK_CourseExemptions_TeachingTasks" FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE RESTRICT);""",
|
||||
|
||||
+6549
File diff suppressed because it is too large
Load Diff
+132
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class TeachingTaskGradeAnalytics : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TeachingTaskGradeStatistics",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
GradeSheetId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
TeachingTaskId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
CourseId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
AcademicTermId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
StudentCount = table.Column<int>(type: "int", nullable: false),
|
||||
PassedCount = table.Column<int>(type: "int", nullable: false),
|
||||
ExcellentCount = table.Column<int>(type: "int", nullable: false),
|
||||
HighestScore = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
|
||||
AverageScore = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
|
||||
MedianScore = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
|
||||
LowestScore = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
|
||||
StandardDeviation = table.Column<decimal>(type: "decimal(6,2)", precision: 6, scale: 2, nullable: false),
|
||||
PassRate = table.Column<decimal>(type: "decimal(5,2)", precision: 5, scale: 2, nullable: false),
|
||||
ExcellentRate = table.Column<decimal>(type: "decimal(5,2)", precision: 5, scale: 2, nullable: false),
|
||||
CalculatedAt = table.Column<DateTime>(type: "datetime(6)", 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_TeachingTaskGradeStatistics", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeachingTaskGradeStatistics_AcademicTerms_AcademicTermId",
|
||||
column: x => x.AcademicTermId,
|
||||
principalTable: "AcademicTerms",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeachingTaskGradeStatistics_Courses_CourseId",
|
||||
column: x => x.CourseId,
|
||||
principalTable: "Courses",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeachingTaskGradeStatistics_GradeSheets_GradeSheetId",
|
||||
column: x => x.GradeSheetId,
|
||||
principalTable: "GradeSheets",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeachingTaskGradeStatistics_TeachingTasks_TeachingTaskId",
|
||||
column: x => x.TeachingTaskId,
|
||||
principalTable: "TeachingTasks",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySQL:Charset", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TeachingTaskGradeScoreBands",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
TeachingTaskGradeStatisticId = table.Column<Guid>(type: "char(36)", nullable: false),
|
||||
Label = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false),
|
||||
LowerBound = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: false),
|
||||
UpperBound = table.Column<decimal>(type: "decimal(5,1)", precision: 5, scale: 1, nullable: true),
|
||||
StudentCount = table.Column<int>(type: "int", 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_TeachingTaskGradeScoreBands", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_TeachingTaskGradeScoreBands_TeachingTaskGradeStatistics_Teac~",
|
||||
column: x => x.TeachingTaskGradeStatisticId,
|
||||
principalTable: "TeachingTaskGradeStatistics",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySQL:Charset", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeachingTaskGradeScoreBands_TeachingTaskGradeStatisticId_Sor~",
|
||||
table: "TeachingTaskGradeScoreBands",
|
||||
columns: new[] { "TeachingTaskGradeStatisticId", "SortOrder" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeachingTaskGradeStatistics_AcademicTermId",
|
||||
table: "TeachingTaskGradeStatistics",
|
||||
column: "AcademicTermId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeachingTaskGradeStatistics_CourseId_AcademicTermId",
|
||||
table: "TeachingTaskGradeStatistics",
|
||||
columns: new[] { "CourseId", "AcademicTermId" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeachingTaskGradeStatistics_GradeSheetId",
|
||||
table: "TeachingTaskGradeStatistics",
|
||||
column: "GradeSheetId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_TeachingTaskGradeStatistics_TeachingTaskId",
|
||||
table: "TeachingTaskGradeStatistics",
|
||||
column: "TeachingTaskId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TeachingTaskGradeScoreBands");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "TeachingTaskGradeStatistics");
|
||||
}
|
||||
}
|
||||
}
|
||||
+183
-15
@@ -996,6 +996,9 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<int>("Below60Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime>("CalculatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
@@ -1005,6 +1008,18 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("From60To69Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From70To79Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From80To89Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From90To100Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("HighestScore")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
@@ -1020,21 +1035,6 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Property<int>("PassedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Below60Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From60To69Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From70To79Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From80To89Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("From90To100Count")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("Scope")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -4109,6 +4109,127 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.ToTable("TeachingTaskClasses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskGradeScoreBand", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<string>("Label")
|
||||
.IsRequired()
|
||||
.HasMaxLength(30)
|
||||
.HasColumnType("varchar(30)");
|
||||
|
||||
b.Property<decimal>("LowerBound")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<int>("SortOrder")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("StudentCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("TeachingTaskGradeStatisticId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<decimal?>("UpperBound")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TeachingTaskGradeStatisticId", "SortOrder")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("TeachingTaskGradeScoreBands");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("AcademicTermId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<decimal>("AverageScore")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<DateTime>("CalculatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<Guid>("CourseId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.Property<int>("ExcellentCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("ExcellentRate")
|
||||
.HasPrecision(5, 2)
|
||||
.HasColumnType("decimal(5,2)");
|
||||
|
||||
b.Property<Guid>("GradeSheetId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<decimal>("HighestScore")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<decimal>("LowestScore")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<decimal>("MedianScore")
|
||||
.HasPrecision(5, 1)
|
||||
.HasColumnType("decimal(5,1)");
|
||||
|
||||
b.Property<decimal>("PassRate")
|
||||
.HasPrecision(5, 2)
|
||||
.HasColumnType("decimal(5,2)");
|
||||
|
||||
b.Property<int>("PassedCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<decimal>("StandardDeviation")
|
||||
.HasPrecision(6, 2)
|
||||
.HasColumnType("decimal(6,2)");
|
||||
|
||||
b.Property<int>("StudentCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<Guid>("TeachingTaskId")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("datetime(6)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AcademicTermId");
|
||||
|
||||
b.HasIndex("GradeSheetId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("TeachingTaskId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("CourseId", "AcademicTermId");
|
||||
|
||||
b.ToTable("TeachingTaskGradeStatistics");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskScheduleConstraint", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -6050,6 +6171,48 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Navigation("TeachingTask");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskGradeScoreBand", b =>
|
||||
{
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", "TeachingTaskGradeStatistic")
|
||||
.WithMany("ScoreBands")
|
||||
.HasForeignKey("TeachingTaskGradeStatisticId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("TeachingTaskGradeStatistic");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", b =>
|
||||
{
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.AcademicTerm", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("AcademicTermId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.Course", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("CourseId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.GradeSheet", "GradeSheet")
|
||||
.WithOne()
|
||||
.HasForeignKey("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", "GradeSheetId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.TeachingTask", "TeachingTask")
|
||||
.WithOne()
|
||||
.HasForeignKey("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", "TeachingTaskId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("GradeSheet");
|
||||
|
||||
b.Navigation("TeachingTask");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskScheduleConstraint", b =>
|
||||
{
|
||||
b.HasOne("Jiaowu.Api.Domain.Academic.Building", "RequiredBuilding")
|
||||
@@ -6368,6 +6531,11 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
b.Navigation("Teachers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskGradeStatistic", b =>
|
||||
{
|
||||
b.Navigation("ScoreBands");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Jiaowu.Api.Domain.Academic.TeachingTaskScheduleConstraint", b =>
|
||||
{
|
||||
b.Navigation("AllowedClassrooms");
|
||||
|
||||
Reference in New Issue
Block a user