优化
This commit is contained in:
@@ -60,8 +60,16 @@ public sealed class DegreeAwardsController(
|
||||
|
||||
[HttpGet("batches/{id:guid}")]
|
||||
[Authorize(Roles = Reviewers)]
|
||||
public async Task<ActionResult> GetBatch(Guid id, CancellationToken token)
|
||||
public async Task<ActionResult> GetBatch(
|
||||
Guid id,
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20,
|
||||
[FromQuery] string? keyword = null,
|
||||
[FromQuery] DegreeAwardConclusion? conclusion = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
page = Math.Max(page, 1);
|
||||
pageSize = Math.Clamp(pageSize, 10, 100);
|
||||
var batch = await db.DegreeAwardBatches.AsNoTracking()
|
||||
.FirstOrDefaultAsync(x => x.Id == id, token);
|
||||
if (batch is null) return NotFound();
|
||||
@@ -71,6 +79,52 @@ public sealed class DegreeAwardsController(
|
||||
if (collegeId.HasValue)
|
||||
source = source.Where(x =>
|
||||
x.Student!.AdministrativeClass!.Major!.CollegeId == collegeId);
|
||||
|
||||
var summary = await source
|
||||
.GroupBy(_ => 1)
|
||||
.Select(group => new
|
||||
{
|
||||
ResultCount = group.Count(),
|
||||
GrantedCount = group.Count(x =>
|
||||
x.Conclusion == DegreeAwardConclusion.Granted),
|
||||
NotGrantedCount = group.Count(x =>
|
||||
x.Conclusion == DegreeAwardConclusion.NotGranted),
|
||||
OverrideCount = group.Count(x => x.IsOverridden)
|
||||
})
|
||||
.FirstOrDefaultAsync(token);
|
||||
|
||||
var normalizedKeyword = keyword?.Trim();
|
||||
if (!string.IsNullOrWhiteSpace(normalizedKeyword))
|
||||
source = source.Where(x =>
|
||||
x.Student!.StudentNumber.Contains(normalizedKeyword) ||
|
||||
x.Student.Name.Contains(normalizedKeyword) ||
|
||||
x.Student.AdministrativeClass!.Name.Contains(normalizedKeyword) ||
|
||||
x.Student.AdministrativeClass.Major!.Name.Contains(normalizedKeyword));
|
||||
if (conclusion.HasValue)
|
||||
source = source.Where(x => x.Conclusion == conclusion.Value);
|
||||
|
||||
var total = await source.CountAsync(token);
|
||||
var items = await source.OrderBy(x => x.Student!.StudentNumber)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.StudentId,
|
||||
x.Student!.StudentNumber,
|
||||
x.Student.Name,
|
||||
ClassName = x.Student.AdministrativeClass!.Name,
|
||||
MajorName = x.Student.AdministrativeClass.Major!.Name,
|
||||
CollegeName = x.Student.AdministrativeClass.Major.College!.Name,
|
||||
x.AverageGradePoint,
|
||||
x.CalculatedConclusion,
|
||||
x.Conclusion,
|
||||
x.ExceptionReason,
|
||||
x.IsOverridden,
|
||||
x.ReviewComment,
|
||||
x.ReviewedAt
|
||||
}).ToListAsync(token);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
batch.Id,
|
||||
@@ -82,24 +136,17 @@ public sealed class DegreeAwardsController(
|
||||
batch.Notes,
|
||||
batch.CalculatedAt,
|
||||
batch.PublishedAt,
|
||||
Results = await source.OrderBy(x => x.Student!.StudentNumber)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.StudentId,
|
||||
x.Student!.StudentNumber,
|
||||
x.Student.Name,
|
||||
ClassName = x.Student.AdministrativeClass!.Name,
|
||||
MajorName = x.Student.AdministrativeClass.Major!.Name,
|
||||
CollegeName = x.Student.AdministrativeClass.Major.College!.Name,
|
||||
x.AverageGradePoint,
|
||||
x.CalculatedConclusion,
|
||||
x.Conclusion,
|
||||
x.ExceptionReason,
|
||||
x.IsOverridden,
|
||||
x.ReviewComment,
|
||||
x.ReviewedAt
|
||||
}).ToListAsync(token)
|
||||
ResultCount = summary?.ResultCount ?? 0,
|
||||
GrantedCount = summary?.GrantedCount ?? 0,
|
||||
NotGrantedCount = summary?.NotGrantedCount ?? 0,
|
||||
OverrideCount = summary?.OverrideCount ?? 0,
|
||||
Results = new
|
||||
{
|
||||
Items = items,
|
||||
Total = total,
|
||||
Page = page,
|
||||
PageSize = pageSize
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -133,25 +180,30 @@ public sealed class DegreeAwardsController(
|
||||
return ConflictProblem("已发布批次不能重新计算。");
|
||||
|
||||
var auditCandidates = await db.GraduationAuditResults.AsNoTracking()
|
||||
.Include(x => x.GraduationAuditBatch)
|
||||
.Include(x => x.Student)
|
||||
.ThenInclude(x => x!.AdministrativeClass)
|
||||
.ThenInclude(x => x!.Major)
|
||||
.Where(x =>
|
||||
x.GraduationAuditBatch!.GraduationYear == batch.GraduationYear &&
|
||||
x.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published &&
|
||||
x.Conclusion == GraduationAuditConclusion.Eligible)
|
||||
.OrderByDescending(x => x.GraduationAuditBatch!.PublishedAt)
|
||||
.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.StudentId,
|
||||
StudentStatus = x.Student!.Status
|
||||
})
|
||||
.ToListAsync(token);
|
||||
var audits = auditCandidates
|
||||
.GroupBy(x => x.StudentId)
|
||||
.Select(x => x.First())
|
||||
.ToList();
|
||||
var studentIds = audits.Select(x => x.StudentId).ToArray();
|
||||
var gradePoints = await db.GradeRecords.AsNoTracking()
|
||||
.Where(x => x.GradeSheet!.Status == GradeSheetStatus.Published &&
|
||||
x.GradePoint.HasValue)
|
||||
.WhereIn(studentIds, x => x.StudentId)
|
||||
.Where(x => db.GraduationAuditResults.Any(audit =>
|
||||
audit.StudentId == x.StudentId &&
|
||||
audit.GraduationAuditBatch!.GraduationYear == batch.GraduationYear &&
|
||||
audit.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published &&
|
||||
audit.Conclusion == GraduationAuditConclusion.Eligible))
|
||||
.Select(x => new
|
||||
{
|
||||
x.StudentId,
|
||||
@@ -159,14 +211,17 @@ public sealed class DegreeAwardsController(
|
||||
x.GradeSheet!.TeachingTask!.Course!.Credits
|
||||
}).ToListAsync(token);
|
||||
|
||||
var oldResults = await db.DegreeAwardResults
|
||||
.Where(x => x.DegreeAwardBatchId == id).ToListAsync(token);
|
||||
db.DegreeAwardResults.RemoveRange(oldResults);
|
||||
await db.SaveChangesAsync(token);
|
||||
var gradePointsByStudent = gradePoints
|
||||
.GroupBy(x => x.StudentId)
|
||||
.ToDictionary(group => group.Key, group => group.ToList());
|
||||
|
||||
await db.DegreeAwardResults
|
||||
.Where(x => x.DegreeAwardBatchId == id)
|
||||
.ExecuteDeleteAsync(token);
|
||||
|
||||
foreach (var audit in audits)
|
||||
{
|
||||
var grades = gradePoints.Where(x => x.StudentId == audit.StudentId).ToList();
|
||||
var grades = gradePointsByStudent.GetValueOrDefault(audit.StudentId) ?? [];
|
||||
var credits = grades.Sum(x => x.Credits);
|
||||
var average = credits == 0
|
||||
? 0
|
||||
@@ -175,8 +230,8 @@ public sealed class DegreeAwardsController(
|
||||
2,
|
||||
MidpointRounding.AwayFromZero);
|
||||
var conclusion = DegreeAwardRules.Evaluate(
|
||||
true, audit.Student!.Status, average, batch.MinimumGradePoint);
|
||||
var reason = audit.Student.Status != StudentStatus.Graduated
|
||||
true, audit.StudentStatus, average, batch.MinimumGradePoint);
|
||||
var reason = audit.StudentStatus != StudentStatus.Graduated
|
||||
? "学籍状态尚未转为毕业"
|
||||
: average < batch.MinimumGradePoint
|
||||
? $"平均绩点 {average:0.00},低于批次要求 {batch.MinimumGradePoint:0.00}"
|
||||
|
||||
Reference in New Issue
Block a user