Skip to content

Commit

Permalink
Add API to create missing course sites (#573)
Browse files Browse the repository at this point in the history
  • Loading branch information
KrisJordan authored Aug 9, 2024
1 parent b058a7f commit c7db817
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
12 changes: 12 additions & 0 deletions backend/api/academics/hiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ def update_hiring_level(
return hiring_service.update_hiring_level(subject, level)


@api.post("/create_sites", tags=["Hiring"])
def create_missing_course_sites_for_term(
term_id: str,
subject: User = Depends(registered_user),
hiring_service: HiringService = Depends(),
) -> bool:
"""
Creates missing course sites for the term
"""
return hiring_service.create_missing_course_sites_for_term(subject, term_id)


@api.get("/{course_site_id}", tags=["Hiring"])
def get_status(
course_site_id: int,
Expand Down
9 changes: 9 additions & 0 deletions backend/entities/academics/section_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ class SectionEntity(EntityBase):
primaryjoin="and_(SectionEntity.id==SectionRoomEntity.section_id, SectionRoomEntity.assignment_type=='OFFICE_HOURS')",
)

def get_title(self) -> str:
"""
Returns the title of the section, either the override title or the course title
Returns:
str: Title of the section
"""
return self.override_title if self.override_title else self.course.title

# Members of the course
members: Mapped[list["SectionMemberEntity"]] = relationship(
back_populates="section", cascade="delete"
Expand Down
9 changes: 9 additions & 0 deletions backend/entities/user_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ class UserEntity(EntityBase):
back_populates="user"
)

def full_name(self) -> str:
"""
Returns the full name of the user.
Returns:
str: The full name of the user.
"""
return f"{self.first_name} {self.last_name}"

@classmethod
def from_model(cls, model: User) -> Self:
"""
Expand Down
37 changes: 37 additions & 0 deletions backend/services/academics/hiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,43 @@ def update_status(
# Reload the data and return the hiring status.
return self.get_status(subject, course_site_id)

def create_missing_course_sites_for_term(self, subject: User, term_id: str) -> bool:
"""
Creates missing course sites for a given term.
"""
self._permission.enforce(
subject, "hiring.create_missing_course_sites_for_term", f"course_sites/*"
)

# Get a list of all sections that are not associated with course sites
section_query = select(SectionEntity).where(
SectionEntity.course_site_id.is_(None)
)
joint: dict[tuple[str, str], list[SectionEntity]] = {}
for section in self._session.scalars(section_query).all():
instructors = [
section_member.user.full_name()
for section_member in section.members
if section_member.member_role == RosterRole.INSTRUCTOR
]
key = (f"{section.course_id}", str(instructors))
if key not in joint:
joint[key] = []
joint[key].append(section)

# Create a course site for each group of sections
for key, sections in joint.items():
course_site = CourseSiteEntity(
term_id=term_id,
title=sections[0].get_title(),
)
for section in sections:
section.course_site = course_site
self._session.add(course_site)

self._session.commit()
return True

def _load_course_site(self, course_site_id: int) -> CourseSiteEntity:
"""
Loads a course site given a subject and course site ID.
Expand Down
13 changes: 13 additions & 0 deletions backend/test/services/academics/hiring/hiring_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
)
from .....services.academics import HiringService
from .....services.application import ApplicationService
from .....services.academics.course_site import CourseSiteService

# Injected Service Fixtures
from .fixtures import hiring_svc
from ..course_site_test import course_site_svc

# Import the setup_teardown fixture explicitly to load entities in database
from ...core_data import setup_insert_data_fixture as insert_order_0
Expand Down Expand Up @@ -281,3 +283,14 @@ def test_update_hiring_level_not_found(hiring_svc: HiringService):
with pytest.raises(ResourceNotFoundException):
hiring_svc.update_hiring_level(user_data.root, hiring_data.new_level)
pytest.fail()


def test_create_missing_course_sites_for_term(
hiring_svc: HiringService, course_site_svc: CourseSiteService
):
user = user_data.root
term = term_data.current_term
overview_pre = hiring_svc.get_hiring_admin_overview(user, term.id)
hiring_svc.create_missing_course_sites_for_term(user, term.id)
overview_post = hiring_svc.get_hiring_admin_overview(user, term.id)
assert len(overview_post.sites) > len(overview_pre.sites)

0 comments on commit c7db817

Please sign in to comment.