修复Mysql
This commit is contained in:
1 parent
634ef69a27
commit
72297aa23f
31 files changed
+725
-275
No files matched your search
@@ -178,13 +178,25 @@ public sealed class AttendanceController(
|
||||
{
|
||||
Sheet = new
|
||||
{
|
||||
sheet.Id, sheet.TeachingTaskId, sheet.Name, sheet.AttendanceDate,
|
||||
sheet.Status, sheet.Notes, sheet.SubmittedAt,
|
||||
sheet.TaskNumber, sheet.TaskName, sheet.CourseCode, sheet.CourseName,
|
||||
sheet.Id,
|
||||
sheet.TeachingTaskId,
|
||||
sheet.Name,
|
||||
sheet.AttendanceDate,
|
||||
sheet.Status,
|
||||
sheet.Notes,
|
||||
sheet.SubmittedAt,
|
||||
sheet.TaskNumber,
|
||||
sheet.TaskName,
|
||||
sheet.CourseCode,
|
||||
sheet.CourseName,
|
||||
Records = sheet.Records.Select(r => new
|
||||
{
|
||||
r.StudentId, r.StudentNumber, r.Name, r.ClassName,
|
||||
r.Status, r.Notes,
|
||||
r.StudentId,
|
||||
r.StudentNumber,
|
||||
r.Name,
|
||||
r.ClassName,
|
||||
r.Status,
|
||||
r.Notes,
|
||||
IsExempt = exemptStudentIds.Contains(r.StudentId),
|
||||
IsDeferred = deferredStudentIds.Contains(r.StudentId)
|
||||
})
|
||||
@@ -504,8 +516,8 @@ public sealed class AttendanceController(
|
||||
|
||||
var source = db.AttendanceRecords.AsNoTracking()
|
||||
.Where(r =>
|
||||
r.AttendanceSheet!.Status == AttendanceSheetStatus.Submitted &&
|
||||
targetClassIds.Contains(r.Student!.AdministrativeClassId));
|
||||
r.AttendanceSheet!.Status == AttendanceSheetStatus.Submitted)
|
||||
.WhereIn(targetClassIds, r => r.Student!.AdministrativeClassId);
|
||||
if (academicTermId.HasValue)
|
||||
source = source.Where(r =>
|
||||
r.AttendanceSheet!.TeachingTask!.AcademicTermId == academicTermId);
|
||||
|
||||
@@ -77,20 +77,30 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
}
|
||||
|
||||
if (rows.Count == 0) return ValidationProblem("Excel 中没有可导入的数据。");
|
||||
return await db.ExecuteInRetriableTransactionAsync<
|
||||
ActionResult<ExcelImportResult>>(
|
||||
async transaction =>
|
||||
{
|
||||
var errors = new List<string>();
|
||||
ExcelImportResult result;
|
||||
await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
result = kind.ToLowerInvariant() switch
|
||||
{
|
||||
"campuses" => await ImportCampusesAsync(rows, errors, cancellationToken),
|
||||
"colleges" => await ImportCollegesAsync(rows, errors, cancellationToken),
|
||||
"majors" => await ImportMajorsAsync(rows, errors, cancellationToken),
|
||||
"classes" => await ImportClassesAsync(rows, errors, cancellationToken),
|
||||
"terms" => await ImportTermsAsync(rows, errors, cancellationToken),
|
||||
"buildings" => await ImportBuildingsAsync(rows, errors, cancellationToken),
|
||||
"classrooms" => await ImportClassroomsAsync(rows, errors, cancellationToken),
|
||||
"campuses" => await ImportCampusesAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"colleges" => await ImportCollegesAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"majors" => await ImportMajorsAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"classes" => await ImportClassesAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"terms" => await ImportTermsAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"buildings" => await ImportBuildingsAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"classrooms" => await ImportClassroomsAsync(
|
||||
rows, errors, cancellationToken),
|
||||
"course-categories" => await ImportCourseCategoriesAsync(
|
||||
rows, errors, cancellationToken),
|
||||
_ => throw new InvalidOperationException()
|
||||
@@ -116,6 +126,8 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
Status = StatusCodes.Status409Conflict
|
||||
});
|
||||
}
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<IReadOnlyList<IReadOnlyList<object?>>> GetExportRowsAsync(
|
||||
@@ -256,7 +268,9 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
{
|
||||
entity = new Major
|
||||
{
|
||||
Code = code, Name = name, CollegeId = college.Id,
|
||||
Code = code,
|
||||
Name = name,
|
||||
CollegeId = college.Id,
|
||||
DegreeType = degreeType
|
||||
};
|
||||
db.Majors.Add(entity);
|
||||
@@ -316,7 +330,10 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
{
|
||||
entity = new AdministrativeClass
|
||||
{
|
||||
Code = code, Name = name, MajorId = major.Id, Grade = grade.Value
|
||||
Code = code,
|
||||
Name = name,
|
||||
MajorId = major.Id,
|
||||
Grade = grade.Value
|
||||
};
|
||||
db.AdministrativeClasses.Add(entity);
|
||||
existing[code] = entity;
|
||||
@@ -362,8 +379,11 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
{
|
||||
entity = new AcademicTerm
|
||||
{
|
||||
Code = code, Name = name, AcademicYear = academicYear,
|
||||
Season = season.Value, StartDate = startDate.Value,
|
||||
Code = code,
|
||||
Name = name,
|
||||
AcademicYear = academicYear,
|
||||
Season = season.Value,
|
||||
StartDate = startDate.Value,
|
||||
EndDate = endDate.Value
|
||||
};
|
||||
db.AcademicTerms.Add(entity);
|
||||
@@ -461,7 +481,9 @@ public sealed class BaseDataExcelController(AppDbContext db) : ControllerBase
|
||||
{
|
||||
entity = new Classroom
|
||||
{
|
||||
Code = code, Name = name, BuildingId = building.Id,
|
||||
Code = code,
|
||||
Name = name,
|
||||
BuildingId = building.Id,
|
||||
RoomType = roomType
|
||||
};
|
||||
db.Classrooms.Add(entity);
|
||||
|
||||
@@ -369,12 +369,12 @@ public sealed class CourseSelectionsController(
|
||||
var source = db.Students.AsNoTracking()
|
||||
.Where(x =>
|
||||
x.Status == StudentStatus.Active &&
|
||||
(offering.IsOpenToAll ||
|
||||
offering.ClassIds.Contains(x.AdministrativeClassId)) &&
|
||||
!db.CourseEnrollments.Any(enrollment =>
|
||||
enrollment.CourseSelectionOfferingId == id &&
|
||||
enrollment.StudentId == x.Id &&
|
||||
enrollment.Status == CourseEnrollmentStatus.Enrolled));
|
||||
if (!offering.IsOpenToAll)
|
||||
source = source.WhereIn(offering.ClassIds, x => x.AdministrativeClassId);
|
||||
if (!string.IsNullOrWhiteSpace(keyword))
|
||||
{
|
||||
keyword = keyword.Trim();
|
||||
@@ -415,9 +415,10 @@ public sealed class CourseSelectionsController(
|
||||
if (studentIds.Length > 100)
|
||||
return ValidationProblem("单次最多可为 100 名学生代选。");
|
||||
|
||||
await using var transaction = await db.Database.BeginTransactionAsync(
|
||||
IsolationLevel.Serializable,
|
||||
cancellationToken);
|
||||
return await db.ExecuteInRetriableTransactionAsync<ActionResult>(
|
||||
async transaction =>
|
||||
{
|
||||
db.ChangeTracker.Clear();
|
||||
var offering = await db.CourseSelectionOfferings
|
||||
.Include(x => x.CourseSelectionRound)
|
||||
.Include(x => x.TeachingTask)
|
||||
@@ -437,7 +438,7 @@ public sealed class CourseSelectionsController(
|
||||
|
||||
var students = await db.Students
|
||||
.Include(x => x.AdministrativeClass)
|
||||
.Where(x => studentIds.Contains(x.Id))
|
||||
.WhereIn(studentIds, x => x.Id)
|
||||
.OrderBy(x => x.StudentNumber)
|
||||
.ToListAsync(cancellationToken);
|
||||
if (students.Count != studentIds.Length)
|
||||
@@ -456,9 +457,8 @@ public sealed class CourseSelectionsController(
|
||||
}
|
||||
|
||||
var existingEnrollments = await db.CourseEnrollments
|
||||
.Where(x =>
|
||||
x.CourseSelectionOfferingId == id &&
|
||||
studentIds.Contains(x.StudentId))
|
||||
.Where(x => x.CourseSelectionOfferingId == id)
|
||||
.WhereIn(studentIds, x => x.StudentId)
|
||||
.ToListAsync(cancellationToken);
|
||||
var alreadyEnrolled = existingEnrollments.FirstOrDefault(x =>
|
||||
x.Status == CourseEnrollmentStatus.Enrolled);
|
||||
@@ -482,11 +482,11 @@ public sealed class CourseSelectionsController(
|
||||
|
||||
var duplicateStudentIds = await db.CourseEnrollments.AsNoTracking()
|
||||
.Where(x =>
|
||||
studentIds.Contains(x.StudentId) &&
|
||||
x.Status == CourseEnrollmentStatus.Enrolled &&
|
||||
x.CourseSelectionOffering!.TeachingTask!.CourseId == task.CourseId &&
|
||||
x.CourseSelectionOffering.CourseSelectionRound!.AcademicTermId ==
|
||||
round.AcademicTermId)
|
||||
.WhereIn(studentIds, x => x.StudentId)
|
||||
.Select(x => x.StudentId)
|
||||
.Distinct()
|
||||
.ToListAsync(cancellationToken);
|
||||
@@ -566,6 +566,9 @@ public sealed class CourseSelectionsController(
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
return Ok(new { EnrolledCount = students.Count });
|
||||
},
|
||||
cancellationToken,
|
||||
IsolationLevel.Serializable);
|
||||
}
|
||||
|
||||
[HttpPost("offerings/{offeringId:guid}/force-enroll")]
|
||||
@@ -581,8 +584,10 @@ public sealed class CourseSelectionsController(
|
||||
if (studentIds.Length > 100)
|
||||
return ValidationProblem("单次最多可为 100 名学生强制选课。");
|
||||
|
||||
await using var transaction = await db.Database.BeginTransactionAsync(
|
||||
IsolationLevel.Serializable, cancellationToken);
|
||||
return await db.ExecuteInRetriableTransactionAsync<ActionResult>(
|
||||
async transaction =>
|
||||
{
|
||||
db.ChangeTracker.Clear();
|
||||
var offering = await db.CourseSelectionOfferings
|
||||
.Include(x => x.CourseSelectionRound)
|
||||
.Include(x => x.TeachingTask)
|
||||
@@ -599,16 +604,15 @@ public sealed class CourseSelectionsController(
|
||||
|
||||
var students = await db.Students
|
||||
.Include(x => x.AdministrativeClass)
|
||||
.Where(x => studentIds.Contains(x.Id))
|
||||
.WhereIn(studentIds, x => x.Id)
|
||||
.OrderBy(x => x.StudentNumber)
|
||||
.ToListAsync(cancellationToken);
|
||||
if (students.Count != studentIds.Length)
|
||||
return ValidationProblem("存在无效的学生档案。");
|
||||
|
||||
var existingEnrollments = await db.CourseEnrollments
|
||||
.Where(x =>
|
||||
x.CourseSelectionOfferingId == offeringId &&
|
||||
studentIds.Contains(x.StudentId))
|
||||
.Where(x => x.CourseSelectionOfferingId == offeringId)
|
||||
.WhereIn(studentIds, x => x.StudentId)
|
||||
.ToListAsync(cancellationToken);
|
||||
var alreadyEnrolled = existingEnrollments
|
||||
.FirstOrDefault(x => x.Status == CourseEnrollmentStatus.Enrolled);
|
||||
@@ -648,6 +652,9 @@ public sealed class CourseSelectionsController(
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
return Ok(new { EnrolledCount = enrolled });
|
||||
},
|
||||
cancellationToken,
|
||||
IsolationLevel.Serializable);
|
||||
}
|
||||
|
||||
[HttpDelete("offerings/{offeringId:guid}/admin-enrollments/{enrollmentId:guid}")]
|
||||
@@ -824,14 +831,15 @@ public sealed class CourseSelectionsController(
|
||||
StudentEnrollmentRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await db.ExecuteInRetriableTransactionAsync<ActionResult>(
|
||||
async transaction =>
|
||||
{
|
||||
db.ChangeTracker.Clear();
|
||||
var student = await CurrentStudentAsync(cancellationToken);
|
||||
if (student is null) return ProfileNotFound();
|
||||
if (student.Status != StudentStatus.Active)
|
||||
return ConflictProblem("只有在籍学生可以选课。");
|
||||
|
||||
await using var transaction = await db.Database.BeginTransactionAsync(
|
||||
IsolationLevel.Serializable,
|
||||
cancellationToken);
|
||||
var offering = await db.CourseSelectionOfferings
|
||||
.Include(x => x.CourseSelectionRound)
|
||||
.Include(x => x.TeachingTask)
|
||||
@@ -963,6 +971,9 @@ public sealed class CourseSelectionsController(
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
return Created(string.Empty, new { existing.Id, IsRetake = isRetake });
|
||||
},
|
||||
cancellationToken,
|
||||
IsolationLevel.Serializable);
|
||||
}
|
||||
|
||||
[HttpDelete("student/enrollments/{id:guid}")]
|
||||
@@ -1159,9 +1170,9 @@ public sealed class CourseSelectionsController(
|
||||
if (taskIds.Count == 0) return [];
|
||||
return await db.ScheduleEntries.AsNoTracking()
|
||||
.Where(x =>
|
||||
taskIds.Contains(x.TeachingTaskId) &&
|
||||
x.SchedulePlan!.AcademicTermId == academicTermId &&
|
||||
x.SchedulePlan.Status == SchedulePlanStatus.Published)
|
||||
.WhereIn(taskIds, x => x.TeachingTaskId)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
Loaded 3 of 31 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user