修复Mysql

This commit is contained in:
2026-07-26 10:19:46 +08:00 Unverified
parent 634ef69a27
commit 72297aa23f
31 changed files with 1642 additions and 1192 deletions
@@ -103,12 +103,14 @@ public sealed class CurriculumPlansController(
})
.ToListAsync(cancellationToken);
var accessibleCollegeIds = majorOptions
.Select(x => x.CollegeId)
.Distinct()
.ToArray();
var accessibleMajors = db.Majors.AsNoTracking().Where(x => x.IsEnabled);
if (collegeId.HasValue)
accessibleMajors = accessibleMajors.Where(
x => x.CollegeId == collegeId.Value);
var colleges = await db.Colleges.AsNoTracking()
.Where(x => x.IsEnabled && accessibleCollegeIds.Contains(x.Id))
.Where(x =>
x.IsEnabled &&
accessibleMajors.Any(major => major.CollegeId == x.Id))
.OrderBy(x => x.SortOrder)
.ThenBy(x => x.Code)
.Select(x => new { x.Id, x.Code, x.Name })
@@ -288,46 +290,57 @@ public sealed class CurriculumPlansController(
[HttpPost("{id:guid}/publish")]
public async Task<ActionResult> Publish(Guid id, CancellationToken cancellationToken)
{
var plan = await ScopedPlans()
.Include(x => x.Major)
.Include(x => x.Modules)
.ThenInclude(x => x.Courses)
.ThenInclude(x => x.Course)
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (plan is null) return NotFound();
if (plan.Status != CurriculumPlanStatus.Draft)
return ConflictProblem("只有草稿方案可以发布。");
if (plan.Modules.Count == 0 || plan.Modules.Any(x => x.Courses.Count == 0))
return ConflictProblem("发布前每个课程模块都必须配置课程。");
if (plan.Modules.Sum(x => x.RequiredCredits) != plan.TotalCredits)
return ConflictProblem("各模块最低学分之和必须等于方案总学分。");
if (plan.Modules.Any(module =>
module.Courses.Sum(x => x.Course!.Credits) < module.RequiredCredits))
return ConflictProblem("存在课程学分合计低于最低学分要求的模块。");
if (plan.Modules.SelectMany(x => x.Courses).GroupBy(x => x.CourseId).Any(x => x.Count() > 1))
return ConflictProblem("同一门课程不能重复加入多个模块。");
if (plan.Modules.SelectMany(x => x.Courses).Any(x =>
x.RecommendedSemester > plan.Major!.SchoolingYears * 2))
return ConflictProblem("建议学期超出了该专业学制。");
return await db.ExecuteInRetriableTransactionAsync<ActionResult>(
async transaction =>
{
db.ChangeTracker.Clear();
var plan = await ScopedPlans()
.Include(x => x.Major)
.Include(x => x.Modules)
.ThenInclude(x => x.Courses)
.ThenInclude(x => x.Course)
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (plan is null) return NotFound();
if (plan.Status != CurriculumPlanStatus.Draft)
return ConflictProblem("只有草稿方案可以发布。");
if (plan.Modules.Count == 0 ||
plan.Modules.Any(x => x.Courses.Count == 0))
return ConflictProblem("发布前每个课程模块都必须配置课程。");
if (plan.Modules.Sum(x => x.RequiredCredits) != plan.TotalCredits)
return ConflictProblem("各模块最低学分之和必须等于方案总学分。");
if (plan.Modules.Any(module =>
module.Courses.Sum(x => x.Course!.Credits) <
module.RequiredCredits))
return ConflictProblem(
"存在课程学分合计低于最低学分要求的模块。");
if (plan.Modules.SelectMany(x => x.Courses)
.GroupBy(x => x.CourseId)
.Any(x => x.Count() > 1))
return ConflictProblem("同一门课程不能重复加入多个模块。");
if (plan.Modules.SelectMany(x => x.Courses).Any(x =>
x.RecommendedSemester >
plan.Major!.SchoolingYears * 2))
return ConflictProblem("建议学期超出了该专业学制。");
await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
var previousPlans = await ScopedPlans()
.Where(x =>
x.Id != plan.Id &&
x.MajorId == plan.MajorId &&
x.EffectiveGrade == plan.EffectiveGrade &&
x.Status == CurriculumPlanStatus.Published)
.ToListAsync(cancellationToken);
foreach (var previous in previousPlans)
{
previous.Status = CurriculumPlanStatus.Archived;
}
var previousPlans = await ScopedPlans()
.Where(x =>
x.Id != plan.Id &&
x.MajorId == plan.MajorId &&
x.EffectiveGrade == plan.EffectiveGrade &&
x.Status == CurriculumPlanStatus.Published)
.ToListAsync(cancellationToken);
foreach (var previous in previousPlans)
{
previous.Status = CurriculumPlanStatus.Archived;
}
plan.Status = CurriculumPlanStatus.Published;
plan.PublishedAt = DateTime.UtcNow;
await db.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return NoContent();
plan.Status = CurriculumPlanStatus.Published;
plan.PublishedAt = DateTime.UtcNow;
await db.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return NoContent();
},
cancellationToken);
}
[HttpPost("{planId:guid}/modules")]