考试排考

This commit is contained in:
2026-07-25 14:51:17 +08:00 Unverified
parent 36049af692
commit 4e7da6709e
12 changed files with 1306 additions and 118 deletions
+45 -9
View File
@@ -176,7 +176,8 @@ public sealed class GradesController(
TermName = x.TeachingTask.AcademicTerm!.Name,
CourseCode = x.TeachingTask.Course!.Code,
CourseName = x.TeachingTask.Course.Name,
CollegeName = x.TeachingTask.Course.College!.Name,
CourseCollegeId = x.TeachingTask.Course.CollegeId,
CourseCollegeName = x.TeachingTask.Course.College!.Name,
x.TeachingTask.Course.Credits,
TeacherNames = x.TeachingTask.Teachers
.OrderByDescending(item => item.IsPrimary)
@@ -231,13 +232,21 @@ public sealed class GradesController(
.Include(x => x.Teachers)
.ThenInclude(x => x.Teacher)
.SingleAsync(x => x.Id == sheet.TeachingTaskId, cancellationToken);
// Determine if current user is from the course's college
var scope = currentUserDataScope.Current;
var isCourseCollegeReviewer = IsReviewer() &&
(scope.Scope == DataScope.All ||
scope.RestrictedCollegeId == sheet.CourseCollegeId);
return Ok(new
{
Sheet = sheet,
CanEdit = CanEditScores(task) &&
sheet.Status is GradeSheetStatus.Draft or GradeSheetStatus.Returned,
CanReview = IsReviewer() && sheet.Status == GradeSheetStatus.Submitted,
CanPublish = IsPublisher() && sheet.Status == GradeSheetStatus.Approved
CanReview = isCourseCollegeReviewer && sheet.Status == GradeSheetStatus.Submitted,
CanPublish = IsPublisher() && sheet.Status == GradeSheetStatus.Approved,
NeedsCollegeReview = sheet.CourseCollegeName
});
}
@@ -376,6 +385,11 @@ public sealed class GradesController(
return ConflictProblem("只有草稿或已退回成绩单可以提交。");
if (sheet.Records.Count == 0)
return ConflictProblem("成绩单没有学生记录。");
// Final recalculation pass before submit
foreach (var record in sheet.Records)
Recalculate(sheet, record);
if (sheet.Records.Any(x =>
x.ExamStatus == GradeExamStatus.Normal &&
!x.TotalScore.HasValue))
@@ -390,11 +404,22 @@ public sealed class GradesController(
[Authorize(Roles = Reviewers)]
public async Task<ActionResult> Approve(Guid id, CancellationToken cancellationToken)
{
var sheet = await AccessibleSheets().FirstOrDefaultAsync(
x => x.Id == id,
cancellationToken);
var sheet = await db.GradeSheets
.Include(x => x.TeachingTask)
.ThenInclude(x => x!.Course)
.ThenInclude(x => x!.College)
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (sheet is null) return NotFound();
if (!IsReviewer()) return Forbid();
// College-specific check: CollegeAdmin must belong to the course's college
var scope = currentUserDataScope.Current;
if (scope.Scope == DataScope.College &&
sheet.TeachingTask!.Course!.CollegeId != scope.RestrictedCollegeId)
return ConflictProblem(
$"该课程属于{sheet.TeachingTask.Course.College!.Name}" +
"您只能审核本学院课程的成绩单。");
if (sheet.Status != GradeSheetStatus.Submitted)
return ConflictProblem("只有待审核成绩单可以通过审核。");
sheet.Status = GradeSheetStatus.Approved;
@@ -410,11 +435,22 @@ public sealed class GradesController(
GradeReviewRequest request,
CancellationToken cancellationToken)
{
var sheet = await AccessibleSheets().FirstOrDefaultAsync(
x => x.Id == id,
cancellationToken);
var sheet = await db.GradeSheets
.Include(x => x.TeachingTask)
.ThenInclude(x => x!.Course)
.ThenInclude(x => x!.College)
.FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
if (sheet is null) return NotFound();
if (!IsReviewer()) return Forbid();
// College-specific check
var scope = currentUserDataScope.Current;
if (scope.Scope == DataScope.College &&
sheet.TeachingTask!.Course!.CollegeId != scope.RestrictedCollegeId)
return ConflictProblem(
$"该课程属于{sheet.TeachingTask.Course.College!.Name}" +
"您只能审核本学院课程的成绩单。");
if (sheet.Status != GradeSheetStatus.Submitted)
return ConflictProblem("只有待审核成绩单可以退回。");
if (string.IsNullOrWhiteSpace(request.Comment))