This commit is contained in:
biss committed 2026-07-26 22:16:58 +08:00
1 parent dd1b752fa3
commit bc6ffa2ada
7 files changed
+562 -126

No files matched your search

@@ -60,8 +60,16 @@ public sealed class DegreeAwardsController(
[HttpGet("batches/{id:guid}")] [HttpGet("batches/{id:guid}")]
[Authorize(Roles = Reviewers)] [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() var batch = await db.DegreeAwardBatches.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id, token); .FirstOrDefaultAsync(x => x.Id == id, token);
if (batch is null) return NotFound(); if (batch is null) return NotFound();
@@ -71,18 +79,34 @@ public sealed class DegreeAwardsController(
if (collegeId.HasValue) if (collegeId.HasValue)
source = source.Where(x => source = source.Where(x =>
x.Student!.AdministrativeClass!.Major!.CollegeId == collegeId); x.Student!.AdministrativeClass!.Major!.CollegeId == collegeId);
return Ok(new
var summary = await source
.GroupBy(_ => 1)
.Select(group => new
{ {
batch.Id, ResultCount = group.Count(),
batch.Name, GrantedCount = group.Count(x =>
batch.GraduationYear, x.Conclusion == DegreeAwardConclusion.Granted),
batch.DegreeName, NotGrantedCount = group.Count(x =>
batch.MinimumGradePoint, x.Conclusion == DegreeAwardConclusion.NotGranted),
batch.Status, OverrideCount = group.Count(x => x.IsOverridden)
batch.Notes, })
batch.CalculatedAt, .FirstOrDefaultAsync(token);
batch.PublishedAt,
Results = await source.OrderBy(x => x.Student!.StudentNumber) 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 .Select(x => new
{ {
x.Id, x.Id,
@@ -99,7 +123,30 @@ public sealed class DegreeAwardsController(
x.IsOverridden, x.IsOverridden,
x.ReviewComment, x.ReviewComment,
x.ReviewedAt x.ReviewedAt
}).ToListAsync(token) }).ToListAsync(token);
return Ok(new
{
batch.Id,
batch.Name,
batch.GraduationYear,
batch.DegreeName,
batch.MinimumGradePoint,
batch.Status,
batch.Notes,
batch.CalculatedAt,
batch.PublishedAt,
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("已发布批次不能重新计算。"); return ConflictProblem("已发布批次不能重新计算。");
var auditCandidates = await db.GraduationAuditResults.AsNoTracking() var auditCandidates = await db.GraduationAuditResults.AsNoTracking()
.Include(x => x.GraduationAuditBatch)
.Include(x => x.Student)
.ThenInclude(x => x!.AdministrativeClass)
.ThenInclude(x => x!.Major)
.Where(x => .Where(x =>
x.GraduationAuditBatch!.GraduationYear == batch.GraduationYear && x.GraduationAuditBatch!.GraduationYear == batch.GraduationYear &&
x.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published && x.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published &&
x.Conclusion == GraduationAuditConclusion.Eligible) x.Conclusion == GraduationAuditConclusion.Eligible)
.OrderByDescending(x => x.GraduationAuditBatch!.PublishedAt) .OrderByDescending(x => x.GraduationAuditBatch!.PublishedAt)
.Select(x => new
{
x.Id,
x.StudentId,
StudentStatus = x.Student!.Status
})
.ToListAsync(token); .ToListAsync(token);
var audits = auditCandidates var audits = auditCandidates
.GroupBy(x => x.StudentId) .GroupBy(x => x.StudentId)
.Select(x => x.First()) .Select(x => x.First())
.ToList(); .ToList();
var studentIds = audits.Select(x => x.StudentId).ToArray();
var gradePoints = await db.GradeRecords.AsNoTracking() var gradePoints = await db.GradeRecords.AsNoTracking()
.Where(x => x.GradeSheet!.Status == GradeSheetStatus.Published && .Where(x => x.GradeSheet!.Status == GradeSheetStatus.Published &&
x.GradePoint.HasValue) 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 .Select(x => new
{ {
x.StudentId, x.StudentId,
@@ -159,14 +211,17 @@ public sealed class DegreeAwardsController(
x.GradeSheet!.TeachingTask!.Course!.Credits x.GradeSheet!.TeachingTask!.Course!.Credits
}).ToListAsync(token); }).ToListAsync(token);
var oldResults = await db.DegreeAwardResults var gradePointsByStudent = gradePoints
.Where(x => x.DegreeAwardBatchId == id).ToListAsync(token); .GroupBy(x => x.StudentId)
db.DegreeAwardResults.RemoveRange(oldResults); .ToDictionary(group => group.Key, group => group.ToList());
await db.SaveChangesAsync(token);
await db.DegreeAwardResults
.Where(x => x.DegreeAwardBatchId == id)
.ExecuteDeleteAsync(token);
foreach (var audit in audits) 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 credits = grades.Sum(x => x.Credits);
var average = credits == 0 var average = credits == 0
? 0 ? 0
@@ -175,8 +230,8 @@ public sealed class DegreeAwardsController(
2, 2,
MidpointRounding.AwayFromZero); MidpointRounding.AwayFromZero);
var conclusion = DegreeAwardRules.Evaluate( var conclusion = DegreeAwardRules.Evaluate(
true, audit.Student!.Status, average, batch.MinimumGradePoint); true, audit.StudentStatus, average, batch.MinimumGradePoint);
var reason = audit.Student.Status != StudentStatus.Graduated var reason = audit.StudentStatus != StudentStatus.Graduated
? "学籍状态尚未转为毕业" ? "学籍状态尚未转为毕业"
: average < batch.MinimumGradePoint : average < batch.MinimumGradePoint
? $"平均绩点 {average:0.00},低于批次要求 {batch.MinimumGradePoint:0.00}" ? $"平均绩点 {average:0.00},低于批次要求 {batch.MinimumGradePoint:0.00}"
@@ -61,8 +61,16 @@ public sealed class GraduationAuditsController(
[HttpGet("batches/{id:guid}")] [HttpGet("batches/{id:guid}")]
[Authorize(Roles = Reviewers)] [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] GraduationAuditConclusion? conclusion = null,
CancellationToken token = default)
{ {
page = Math.Max(page, 1);
pageSize = Math.Clamp(pageSize, 10, 100);
var batch = await db.GraduationAuditBatches.AsNoTracking() var batch = await db.GraduationAuditBatches.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id, token); .FirstOrDefaultAsync(x => x.Id == id, token);
if (batch is null) return NotFound(); if (batch is null) return NotFound();
@@ -73,18 +81,35 @@ public sealed class GraduationAuditsController(
if (collegeId.HasValue) if (collegeId.HasValue)
results = results.Where(x => results = results.Where(x =>
x.Student!.AdministrativeClass!.Major!.CollegeId == collegeId); x.Student!.AdministrativeClass!.Major!.CollegeId == collegeId);
return Ok(new
var summary = await results
.GroupBy(_ => 1)
.Select(group => new
{ {
batch.Id, ResultCount = group.Count(),
batch.Name, EligibleCount = group.Count(x =>
batch.GraduationYear, x.Conclusion == GraduationAuditConclusion.Eligible),
batch.EnrollmentYear, IneligibleCount = group.Count(x =>
batch.Status, x.Conclusion == GraduationAuditConclusion.Ineligible),
batch.Notes, OverrideCount = group.Count(x => x.IsOverridden)
batch.CalculatedAt, })
batch.PublishedAt, .FirstOrDefaultAsync(token);
Results = await results
var normalizedKeyword = keyword?.Trim();
if (!string.IsNullOrWhiteSpace(normalizedKeyword))
results = results.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)
results = results.Where(x => x.Conclusion == conclusion.Value);
var total = await results.CountAsync(token);
var items = await results
.OrderBy(x => x.Student!.StudentNumber) .OrderBy(x => x.Student!.StudentNumber)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new .Select(x => new
{ {
x.Id, x.Id,
@@ -107,7 +132,29 @@ public sealed class GraduationAuditsController(
x.IsOverridden, x.IsOverridden,
x.ReviewComment, x.ReviewComment,
x.ReviewedAt x.ReviewedAt
}).ToListAsync(token) }).ToListAsync(token);
return Ok(new
{
batch.Id,
batch.Name,
batch.GraduationYear,
batch.EnrollmentYear,
batch.Status,
batch.Notes,
batch.CalculatedAt,
batch.PublishedAt,
ResultCount = summary?.ResultCount ?? 0,
EligibleCount = summary?.EligibleCount ?? 0,
IneligibleCount = summary?.IneligibleCount ?? 0,
OverrideCount = summary?.OverrideCount ?? 0,
Results = new
{
Items = items,
Total = total,
Page = page,
PageSize = pageSize
}
}); });
} }
@@ -156,10 +203,11 @@ public sealed class GraduationAuditsController(
.Where(x => x.EffectiveGrade == batch.EnrollmentYear && .Where(x => x.EffectiveGrade == batch.EnrollmentYear &&
x.Status == CurriculumPlanStatus.Published) x.Status == CurriculumPlanStatus.Published)
.ToListAsync(token); .ToListAsync(token);
var studentIds = students.Select(x => x.Id).ToArray();
var grades = await db.GradeRecords.AsNoTracking() var grades = await db.GradeRecords.AsNoTracking()
.Where(x => x.GradeSheet!.Status == GradeSheetStatus.Published) .Where(x => x.GradeSheet!.Status == GradeSheetStatus.Published)
.WhereIn(studentIds, x => x.StudentId) .Where(x => x.Student!.EnrollmentYear == batch.EnrollmentYear &&
(x.Student.Status == StudentStatus.Active ||
x.Student.Status == StudentStatus.Suspended))
.Select(x => new GradeSnapshot( .Select(x => new GradeSnapshot(
x.StudentId, x.StudentId,
x.GradeSheet!.TeachingTask!.CourseId, x.GradeSheet!.TeachingTask!.CourseId,
@@ -169,16 +217,23 @@ public sealed class GraduationAuditsController(
x.ExamStatus)) x.ExamStatus))
.ToListAsync(token); .ToListAsync(token);
var oldResults = await db.GraduationAuditResults var plansByMajor = plans
.Where(x => x.GraduationAuditBatchId == id).ToListAsync(token); .GroupBy(x => x.MajorId)
db.GraduationAuditResults.RemoveRange(oldResults); .ToDictionary(group => group.Key, group => group.First());
await db.SaveChangesAsync(token); var gradesByStudent = grades
.GroupBy(x => x.StudentId)
.ToDictionary(group => group.Key, group => group.ToList());
await db.GraduationAuditResults
.Where(x => x.GraduationAuditBatchId == id)
.ExecuteDeleteAsync(token);
foreach (var student in students) foreach (var student in students)
{ {
var plan = plans.FirstOrDefault(x => plansByMajor.TryGetValue(
x.MajorId == student.AdministrativeClass!.MajorId); student.AdministrativeClass!.MajorId,
var studentGrades = grades.Where(x => x.StudentId == student.Id).ToList(); out var plan);
var studentGrades = gradesByStudent.GetValueOrDefault(student.Id) ?? [];
var passedCourseIds = studentGrades var passedCourseIds = studentGrades
.Where(IsPassed) .Where(IsPassed)
.Select(x => x.CourseId) .Select(x => x.CourseId)
@@ -34,31 +34,46 @@ public sealed class GraduationClearanceController(
x.Id, x.Name, x.GraduationYear, x.Status, x.Notes, x.Id, x.Name, x.GraduationYear, x.Status, x.Notes,
x.ClosedAt, x.CreatedAt, ItemCount = x.Items.Count x.ClosedAt, x.CreatedAt, ItemCount = x.Items.Count
}).ToListAsync(token); }).ToListAsync(token);
var records = await ScopedRecords().AsNoTracking() var statistics = await ScopedRecords().AsNoTracking()
.Select(x => new .GroupBy(x => x.GraduationClearanceItem!.GraduationClearanceBatchId)
.Select(group => new
{ {
BatchId = x.GraduationClearanceItem!.GraduationClearanceBatchId, BatchId = group.Key,
x.StudentId, x.Status StudentCount = group.Select(x => x.StudentId).Distinct().Count(),
}).ToListAsync(token); RecordCount = group.Count(),
CompletedCount = group.Count(x =>
x.Status != GraduationClearanceRecordStatus.Pending)
}).ToDictionaryAsync(x => x.BatchId, token);
return Ok(batches.Select(batch => return Ok(batches.Select(batch =>
{ {
var scoped = records.Where(x => x.BatchId == batch.Id).ToList(); statistics.TryGetValue(batch.Id, out var summary);
return new return new
{ {
batch.Id, batch.Name, batch.GraduationYear, batch.Status, batch.Id, batch.Name, batch.GraduationYear, batch.Status,
batch.Notes, batch.ClosedAt, batch.CreatedAt, batch.ItemCount, batch.Notes, batch.ClosedAt, batch.CreatedAt, batch.ItemCount,
StudentCount = scoped.Select(x => x.StudentId).Distinct().Count(), StudentCount = summary?.StudentCount ?? 0,
RecordCount = scoped.Count, RecordCount = summary?.RecordCount ?? 0,
CompletedCount = scoped.Count(x => CompletedCount = summary?.CompletedCount ?? 0
x.Status != GraduationClearanceRecordStatus.Pending)
}; };
})); }));
} }
[HttpGet("batches/{id:guid}")] [HttpGet("batches/{id:guid}")]
[Authorize(Roles = Workers)] [Authorize(Roles = Workers)]
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] string? progress = null,
CancellationToken token = default)
{ {
page = Math.Max(page, 1);
pageSize = Math.Clamp(pageSize, 10, 100);
var normalizedProgress = progress?.Trim();
if (normalizedProgress is not null and not "Pending" and not "Completed")
return ValidationProblem("离校办理进度筛选值无效。");
var batch = await db.GraduationClearanceBatches.AsNoTracking() var batch = await db.GraduationClearanceBatches.AsNoTracking()
.Where(x => x.Id == id) .Where(x => x.Id == id)
.Select(x => new .Select(x => new
@@ -72,8 +87,56 @@ public sealed class GraduationClearanceController(
}) })
}).FirstOrDefaultAsync(token); }).FirstOrDefaultAsync(token);
if (batch is null) return NotFound(); if (batch is null) return NotFound();
var records = await ScopedRecords().AsNoTracking()
.Where(x => x.GraduationClearanceItem!.GraduationClearanceBatchId == id) var records = ScopedRecords().AsNoTracking()
.Where(x => x.GraduationClearanceItem!.GraduationClearanceBatchId == id);
var summary = await records
.GroupBy(_ => 1)
.Select(group => new
{
StudentCount = group.Select(x => x.StudentId).Distinct().Count(),
RecordCount = group.Count(),
CompletedCount = group.Count(x =>
x.Status != GraduationClearanceRecordStatus.Pending)
})
.FirstOrDefaultAsync(token);
var students = db.Students.AsNoTracking()
.Where(student => records.Any(record => record.StudentId == student.Id));
var normalizedKeyword = keyword?.Trim();
if (!string.IsNullOrWhiteSpace(normalizedKeyword))
students = students.Where(student =>
student.StudentNumber.Contains(normalizedKeyword) ||
student.Name.Contains(normalizedKeyword) ||
student.AdministrativeClass!.Name.Contains(normalizedKeyword) ||
student.AdministrativeClass.Major!.Name.Contains(normalizedKeyword));
if (normalizedProgress == "Pending")
students = students.Where(student => records.Any(record =>
record.StudentId == student.Id &&
record.GraduationClearanceItem!.IsRequired &&
record.Status == GraduationClearanceRecordStatus.Pending));
else if (normalizedProgress == "Completed")
students = students.Where(student => !records.Any(record =>
record.StudentId == student.Id &&
record.GraduationClearanceItem!.IsRequired &&
record.Status == GraduationClearanceRecordStatus.Pending));
var total = await students.CountAsync(token);
var studentPage = await students
.OrderBy(student => student.StudentNumber)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(student => new
{
student.Id,
student.StudentNumber,
student.Name,
ClassName = student.AdministrativeClass!.Name,
MajorName = student.AdministrativeClass.Major!.Name
}).ToListAsync(token);
var studentIds = studentPage.Select(student => student.Id).ToArray();
var pageRecords = await records
.WhereIn(studentIds, x => x.StudentId)
.OrderBy(x => x.Student!.StudentNumber) .OrderBy(x => x.Student!.StudentNumber)
.ThenBy(x => x.GraduationClearanceItem!.SortOrder) .ThenBy(x => x.GraduationClearanceItem!.SortOrder)
.Select(x => new .Select(x => new
@@ -89,11 +152,32 @@ public sealed class GraduationClearanceController(
x.GraduationClearanceItem.IsRequired, x.GraduationClearanceItem.IsRequired,
x.Status, x.Notes, x.CompletedAt x.Status, x.Notes, x.CompletedAt
}).ToListAsync(token); }).ToListAsync(token);
var recordsByStudent = pageRecords
.GroupBy(record => record.StudentId)
.ToDictionary(group => group.Key, group => group.ToList());
var studentItems = studentPage.Select(student => new
{
StudentId = student.Id,
student.StudentNumber,
student.Name,
student.ClassName,
student.MajorName,
Records = recordsByStudent.GetValueOrDefault(student.Id) ?? []
}).ToList();
return Ok(new return Ok(new
{ {
batch.Id, batch.Name, batch.GraduationYear, batch.Status, batch.Id, batch.Name, batch.GraduationYear, batch.Status,
batch.Notes, batch.ClosedAt, batch.CreatedAt, batch.Items, batch.Notes, batch.ClosedAt, batch.CreatedAt, batch.Items,
Records = records StudentCount = summary?.StudentCount ?? 0,
RecordCount = summary?.RecordCount ?? 0,
CompletedCount = summary?.CompletedCount ?? 0,
Students = new
{
Items = studentItems,
Total = total,
Page = page,
PageSize = pageSize
}
}); });
} }
@@ -150,16 +234,15 @@ public sealed class GraduationClearanceController(
if (batch.Status != GraduationClearanceBatchStatus.Open) if (batch.Status != GraduationClearanceBatchStatus.Open)
return ConflictProblem("已关闭批次不能重新生成办理记录。"); return ConflictProblem("已关闭批次不能重新生成办理记录。");
var eligibleAudits = await db.GraduationAuditResults.AsNoTracking() var studentIds = await db.GraduationAuditResults.AsNoTracking()
.Where(x => .Where(x =>
x.GraduationAuditBatch!.GraduationYear == batch.GraduationYear && x.GraduationAuditBatch!.GraduationYear == batch.GraduationYear &&
x.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published && x.GraduationAuditBatch.Status == GraduationAuditBatchStatus.Published &&
x.Conclusion == GraduationAuditConclusion.Eligible && x.Conclusion == GraduationAuditConclusion.Eligible &&
x.Student!.Status == StudentStatus.Graduated) x.Student!.Status == StudentStatus.Graduated)
.OrderByDescending(x => x.GraduationAuditBatch!.PublishedAt) .Select(x => x.StudentId)
.Select(x => new { x.StudentId }) .Distinct()
.ToListAsync(token); .ToListAsync(token);
var studentIds = eligibleAudits.Select(x => x.StudentId).Distinct().ToArray();
var existing = await db.GraduationClearanceRecords.AsNoTracking() var existing = await db.GraduationClearanceRecords.AsNoTracking()
.Where(x => x.GraduationClearanceItem!.GraduationClearanceBatchId == id) .Where(x => x.GraduationClearanceItem!.GraduationClearanceBatchId == id)
.Select(x => new { x.GraduationClearanceItemId, x.StudentId }) .Select(x => new { x.GraduationClearanceItemId, x.StudentId })
@@ -180,7 +263,7 @@ public sealed class GraduationClearanceController(
created++; created++;
} }
await db.SaveChangesAsync(token); await db.SaveChangesAsync(token);
return Ok(new { StudentCount = studentIds.Length, CreatedRecordCount = created }); return Ok(new { StudentCount = studentIds.Count, CreatedRecordCount = created });
} }
[HttpPut("records/{id:guid}")] [HttpPut("records/{id:guid}")]
@@ -221,15 +304,17 @@ public sealed class GraduationClearanceController(
public async Task<ActionResult> Close(Guid id, CancellationToken token) public async Task<ActionResult> Close(Guid id, CancellationToken token)
{ {
var batch = await db.GraduationClearanceBatches var batch = await db.GraduationClearanceBatches
.Include(x => x.Items)
.ThenInclude(x => x.Records)
.FirstOrDefaultAsync(x => x.Id == id, token); .FirstOrDefaultAsync(x => x.Id == id, token);
if (batch is null) return NotFound(); if (batch is null) return NotFound();
if (batch.Status != GraduationClearanceBatchStatus.Open) if (batch.Status != GraduationClearanceBatchStatus.Open)
return ConflictProblem("该批次已经关闭。"); return ConflictProblem("该批次已经关闭。");
var records = batch.Items.SelectMany(item => item.Records.Select(record => var hasIncompleteRequiredItem = await db.GraduationClearanceRecords
(item.IsRequired, record.Status))); .AnyAsync(record =>
if (!GraduationClearanceRules.CanClose(records)) record.GraduationClearanceItem!.GraduationClearanceBatchId == id &&
record.GraduationClearanceItem.IsRequired &&
record.Status == GraduationClearanceRecordStatus.Pending,
token);
if (hasIncompleteRequiredItem)
return ConflictProblem("仍有必办离校事项尚未完成。"); return ConflictProblem("仍有必办离校事项尚未完成。");
batch.Status = GraduationClearanceBatchStatus.Closed; batch.Status = GraduationClearanceBatchStatus.Closed;
batch.ClosedAt = DateTime.UtcNow; batch.ClosedAt = DateTime.UtcNow;
Loaded 3 of 7 files, more files were not shown because too many files have changed in this diff. Show more