修复实验成绩评分方案保存的外键失败
This commit is contained in:
1 parent
0e02d446ba
commit
bcdb00ee2e
2 files changed
+95
-9
No files matched your search
@@ -568,21 +568,39 @@ public sealed class ExperimentGradesController(
|
|||||||
|
|
||||||
sheet.ContributionWeight = request.ContributionWeight;
|
sheet.ContributionWeight = request.ContributionWeight;
|
||||||
sheet.PassScore = request.PassScore;
|
sheet.PassScore = request.PassScore;
|
||||||
db.ExperimentGradeItems.RemoveRange(sheet.Items);
|
var existingItems = sheet.Items.ToList();
|
||||||
|
var existingItemScores = sheet.Records
|
||||||
|
.SelectMany(record => record.ItemScores)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// MySQL must see each replacement item before its score rows. Do not
|
||||||
|
// rely on a single mixed insert/delete batch to infer that order.
|
||||||
|
await using var transaction =
|
||||||
|
await db.Database.BeginTransactionAsync(cancellationToken);
|
||||||
|
db.ExperimentGradeItemScores.RemoveRange(existingItemScores);
|
||||||
|
db.ExperimentGradeItems.RemoveRange(existingItems);
|
||||||
foreach (var record in sheet.Records)
|
foreach (var record in sheet.Records)
|
||||||
{
|
{
|
||||||
record.ItemScores.Clear();
|
|
||||||
record.TotalScore = null;
|
record.TotalScore = null;
|
||||||
record.IsPassed = null;
|
record.IsPassed = null;
|
||||||
}
|
}
|
||||||
sheet.Items = replacementItems;
|
|
||||||
foreach (var record in sheet.Records)
|
|
||||||
foreach (var item in replacementItems)
|
|
||||||
record.ItemScores.Add(new ExperimentGradeItemScore
|
|
||||||
{
|
|
||||||
ExperimentGradeItemId = item.Id
|
|
||||||
});
|
|
||||||
await db.SaveChangesAsync(cancellationToken);
|
await db.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
foreach (var item in replacementItems)
|
||||||
|
item.ExperimentGradeSheetId = sheet.Id;
|
||||||
|
db.ExperimentGradeItems.AddRange(replacementItems);
|
||||||
|
await db.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
db.ExperimentGradeItemScores.AddRange(
|
||||||
|
sheet.Records.SelectMany(record => replacementItems.Select(item =>
|
||||||
|
new ExperimentGradeItemScore
|
||||||
|
{
|
||||||
|
ExperimentGradeRecordId = record.Id,
|
||||||
|
ExperimentGradeItemId = item.Id
|
||||||
|
})));
|
||||||
|
await db.SaveChangesAsync(cancellationToken);
|
||||||
|
await transaction.CommitAsync(cancellationToken);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,74 @@ namespace Jiaowu.Api.Tests;
|
|||||||
|
|
||||||
public sealed class ExperimentGradesControllerTests
|
public sealed class ExperimentGradesControllerTests
|
||||||
{
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task UpdateSettings_ReplacesItemsAndRecreatesScores()
|
||||||
|
{
|
||||||
|
await using var fixture = await ExperimentGradeFixture.CreateAsync();
|
||||||
|
var project = new ExperimentProject
|
||||||
|
{
|
||||||
|
TeachingTaskId = fixture.Task.Id,
|
||||||
|
Code = "LAB-SETTINGS",
|
||||||
|
Name = "评分方案更新实验",
|
||||||
|
ArrangementMode = ExperimentArrangementMode.Centralized,
|
||||||
|
StartDate = fixture.Term.StartDate,
|
||||||
|
EndDate = fixture.Term.EndDate,
|
||||||
|
Status = ExperimentProjectStatus.Published,
|
||||||
|
PublishedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
fixture.Db.ExperimentProjects.Add(project);
|
||||||
|
await fixture.Db.SaveChangesAsync();
|
||||||
|
|
||||||
|
var administrator = fixture.ExperimentGrades(fixture.AdminScope);
|
||||||
|
await administrator.CreateSheet(
|
||||||
|
new ExperimentGradeSheetRequest(
|
||||||
|
project.Id,
|
||||||
|
1,
|
||||||
|
60,
|
||||||
|
[new ExperimentGradeItemRequest(
|
||||||
|
"旧评分项",
|
||||||
|
ExperimentGradeItemKind.Operation,
|
||||||
|
100)]),
|
||||||
|
CancellationToken.None);
|
||||||
|
var sheetId = await fixture.Db.ExperimentGradeSheets
|
||||||
|
.Select(sheet => sheet.Id)
|
||||||
|
.SingleAsync();
|
||||||
|
fixture.Db.ChangeTracker.Clear();
|
||||||
|
|
||||||
|
Assert.IsType<NoContentResult>(await administrator.UpdateSettings(
|
||||||
|
sheetId,
|
||||||
|
new ExperimentGradeSettingsRequest(
|
||||||
|
1,
|
||||||
|
60,
|
||||||
|
[
|
||||||
|
new ExperimentGradeItemRequest(
|
||||||
|
"操作",
|
||||||
|
ExperimentGradeItemKind.Operation,
|
||||||
|
60),
|
||||||
|
new ExperimentGradeItemRequest(
|
||||||
|
"报告",
|
||||||
|
ExperimentGradeItemKind.Report,
|
||||||
|
40)
|
||||||
|
]),
|
||||||
|
CancellationToken.None));
|
||||||
|
|
||||||
|
fixture.Db.ChangeTracker.Clear();
|
||||||
|
var updatedSheet = await fixture.Db.ExperimentGradeSheets
|
||||||
|
.Include(sheet => sheet.Items)
|
||||||
|
.Include(sheet => sheet.Records)
|
||||||
|
.ThenInclude(record => record.ItemScores)
|
||||||
|
.SingleAsync(sheet => sheet.Id == sheetId);
|
||||||
|
Assert.Equal(["操作", "报告"], updatedSheet.Items
|
||||||
|
.OrderBy(item => item.SortOrder)
|
||||||
|
.Select(item => item.Name));
|
||||||
|
var record = Assert.Single(updatedSheet.Records);
|
||||||
|
Assert.Equal(2, record.ItemScores.Count);
|
||||||
|
Assert.All(record.ItemScores, score => Assert.Null(score.Score));
|
||||||
|
Assert.All(record.ItemScores, score => Assert.Contains(
|
||||||
|
updatedSheet.Items,
|
||||||
|
item => item.Id == score.ExperimentGradeItemId));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CollegeAdmin_CanPublishApprovedExperimentGradeSheet()
|
public async Task CollegeAdmin_CanPublishApprovedExperimentGradeSheet()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user