Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions backend/app/repositories/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,19 @@ def double_booked(db: Session, assignments: list[FacultyAssignment], meeting_tim
if section.time_block_id == meeting_time:
return True
return False


def crosslist_group_section_ids(db: Session, section_id: int) -> set[int]:
ids: set[int] = {section_id}
section = get_by_id(db, section_id)
if section is None:
return ids

if section.crosslisted_section_id is not None:
ids.add(section.crosslisted_section_id)

reverse = db.query(Section).filter(Section.crosslisted_section_id == section_id).first()
if reverse is not None:
ids.add(reverse.section_id)

return ids
3 changes: 2 additions & 1 deletion backend/app/services/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ def error_check(db: Session, section: Section, updates: SectionUpdate | None = N
return []
warnings = []
faculty_nuids = section_repo.get_faculty_assignmnets(db, section.section_id)
crosslist_ids = section_repo.crosslist_group_section_ids(db, section.section_id)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

if section.time_block_id is not None:
schedule = schedule_repo.get_by_id(db, section.schedule_id)
Expand All @@ -327,7 +328,7 @@ def error_check(db: Session, section: Section, updates: SectionUpdate | None = N
warnings.append(WarningType.TIME_BLOCK_OVERLOAD)

for nuid in faculty_nuids:
other_assignments = [a for a in faculty_repo.get_assignments(db, nuid, section.schedule_id) if a.section_id != section.section_id]
other_assignments = [a for a in faculty_repo.get_assignments(db, nuid, section.schedule_id) if a.section_id not in crosslist_ids]
if section.time_block_id is not None:
if not faculty_repo.find_meeting_time_preference(db, nuid, section.time_block_id):
warnings.append(WarningType.UNPREFERENCED_TIME)
Expand Down
33 changes: 33 additions & 0 deletions backend/tests/test_section_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,39 @@ def test_error_check_empty_faculty_nuids_no_warning(db_session):
assert WarningType.FACULTY_OVERLOAD not in warnings


def test_error_check_crosslisted_sections_not_double_booked(db_session):
campus = _make_campus(db_session)
semester = _make_semester(db_session)
schedule = _make_schedule(db_session, campus, semester)
course = _make_course(db_session, name="CS 2500", code=2500)
tb = _make_time_block(db_session, campus)
faculty = _make_faculty(db_session, campus, nuid=1001, email="f1@test.edu")

a = _make_section(db_session, schedule, course, tb, number=1)
b = _make_section(db_session, schedule, course, tb, number=2)
# Crosslist them as partners.
a.crosslisted_section_id = b.section_id
b.crosslisted_section_id = a.section_id

db_session.add(FacultyAssignment(faculty_nuid=faculty.nuid, section_id=a.section_id))
db_session.add(FacultyAssignment(faculty_nuid=faculty.nuid, section_id=b.section_id))
db_session.commit()

warnings_a = section_service.error_check(db_session, a, SectionUpdate(faculty_nuids=[faculty.nuid]))
warnings_b = section_service.error_check(db_session, b, SectionUpdate(faculty_nuids=[faculty.nuid]))

assert WarningType.FACULTY_DOUBLE_BOOKED not in warnings_a
assert WarningType.FACULTY_DOUBLE_BOOKED not in warnings_b

# A third, non-crosslisted section at the same time block should still trigger a real double-booking warning.
c = _make_section(db_session, schedule, course, tb, number=3)
db_session.add(FacultyAssignment(faculty_nuid=faculty.nuid, section_id=c.section_id))
db_session.commit()

warnings_c = section_service.error_check(db_session, c, SectionUpdate(faculty_nuids=[faculty.nuid]))
assert WarningType.FACULTY_DOUBLE_BOOKED in warnings_c


# ---------------------------------------------------------------------------
# update_section — basic behavior
# ---------------------------------------------------------------------------
Expand Down
Loading