refreshStudentRoster method
Refreshes a course offering's student roster from I-School Plus.
Network work completes before the transaction begins, so any failure leaves the existing cached roster untouched.
Implementation
Future<void> refreshStudentRoster({
required int courseOfferingId,
required String courseNumber,
}) async {
final studentDtos = await _authRepository.withAuth(() async {
final courses = await _iSchoolPlusService.getCourseList();
final course = courses.where(
(course) => course.courseNumber == courseNumber,
);
if (course.isEmpty) return const <StudentDto>[];
return _iSchoolPlusService.getStudents(course.first);
}, sso: [.iSchoolPlusService]);
final seenStudentIds = <String>{};
final students = <({String studentId, String? name})>[];
var skippedStudents = 0;
for (final dto in studentDtos) {
final studentId = dto.id?.trim();
if (studentId == null ||
studentId.isEmpty ||
!seenStudentIds.add(studentId)) {
skippedStudents++;
continue;
}
students.add((
studentId: studentId,
name: switch (dto.name?.trim()) {
final name? when name.isNotEmpty => name,
_ => null,
},
));
}
if (skippedStudents > 0) {
_firebaseService.recordNonFatal(
'Skipped $skippedStudents invalid or duplicate students while '
'refreshing roster for $courseNumber',
);
}
await _database.transaction(() async {
await (_database.delete(_database.courseOfferingStudents)..where(
(row) => row.courseOffering.equals(courseOfferingId),
))
.go();
for (final student in students) {
final studentId = await _database.upsertStudent(
studentId: student.studentId,
name: student.name,
);
await _database
.into(_database.courseOfferingStudents)
.insert(
CourseOfferingStudentsCompanion.insert(
courseOffering: courseOfferingId,
student: studentId,
),
);
}
await (_database.update(_database.courseOfferings)..where(
(offering) => offering.id.equals(courseOfferingId),
))
.write(
CourseOfferingsCompanion(
studentRosterFetchedAt: Value(DateTime.now()),
),
);
});
}