refreshStudentRoster method

Future<void> refreshStudentRoster({
  1. required int courseOfferingId,
  2. required String courseNumber,
})

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()),
          ),
        );
  });
}