Prevent duplicate equivalency rules and support safe deletion

This commit is contained in:
biss committed 2026-08-18 10:30:23 +08:00
1 parent 73f870221b
commit 370a82d4d4
2 files changed
+56 -2

No files matched your search

@@ -40,6 +40,8 @@ public sealed class CourseEquivalencyRulesController(
return Forbid();
if (request.MajorId.HasValue && !await db.Majors.AnyAsync(x => x.Id == request.MajorId && (!collegeId.HasValue || x.CollegeId == collegeId), token))
return ValidationProblem("适用专业不在当前维护范围内。");
if (await HasSameScopeRuleAsync(request, null, token))
return ConflictProblem();
var rule = new CourseEquivalencyRule { OriginalCourseId = request.OriginalCourseId, SubstituteCourseId = request.SubstituteCourseId,
MajorId = request.MajorId, EffectiveGrade = request.EffectiveGrade, IsEnabled = request.IsEnabled, Notes = request.Notes?.Trim() };
db.CourseEquivalencyRules.Add(rule);
@@ -58,11 +60,48 @@ public sealed class CourseEquivalencyRulesController(
var collegeId = scope.Current.RestrictedCollegeId;
if (request.MajorId.HasValue && !await db.Majors.AnyAsync(x => x.Id == request.MajorId && (!collegeId.HasValue || x.CollegeId == collegeId), token))
return ValidationProblem("适用专业不在当前维护范围内。");
if (await HasSameScopeRuleAsync(request, id, token))
return ConflictProblem();
rule.MajorId = request.MajorId; rule.EffectiveGrade = request.EffectiveGrade; rule.IsEnabled = request.IsEnabled; rule.Notes = request.Notes?.Trim();
await db.SaveChangesAsync(token);
return NoContent();
}
[HttpDelete("{id:guid}")]
public async Task<ActionResult> Delete(Guid id, CancellationToken token)
{
var rule = await Scoped(scope.Current.RestrictedCollegeId)
.FirstOrDefaultAsync(x => x.Id == id, token);
if (rule is null) return NotFound();
if (await db.CourseSubstitutions.AnyAsync(
x => x.CourseEquivalencyRuleId == id, token))
return Conflict(new ProblemDetails
{
Title = "该规则已有课程替代申请引用,不能删除;请改为停用以保留审批和毕业审核留痕。",
Status = StatusCodes.Status409Conflict
});
db.CourseEquivalencyRules.Remove(rule);
await db.SaveChangesAsync(token);
return NoContent();
}
private Task<bool> HasSameScopeRuleAsync(
CourseEquivalencyRuleRequest request,
Guid? exceptId,
CancellationToken token) => db.CourseEquivalencyRules.AnyAsync(x =>
x.OriginalCourseId == request.OriginalCourseId &&
x.SubstituteCourseId == request.SubstituteCourseId &&
x.MajorId == request.MajorId &&
x.EffectiveGrade == request.EffectiveGrade &&
(!exceptId.HasValue || x.Id != exceptId.Value), token);
private static ConflictObjectResult ConflictProblem() =>
new(new ProblemDetails
{
Title = "相同适用范围的等价课程规则已存在。",
Status = StatusCodes.Status409Conflict
});
private IQueryable<CourseEquivalencyRule> Scoped(Guid? collegeId) => collegeId.HasValue
? db.CourseEquivalencyRules.Where(x => x.OriginalCourse!.CollegeId == collegeId.Value)
: db.CourseEquivalencyRules;