Skip to content

Commit

Permalink
Merge branch 'main' into feature/check-in-day-icons
Browse files Browse the repository at this point in the history
  • Loading branch information
taesungh authored Jan 26, 2024
2 parents c40321c + fbbc82d commit 4a75340
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 18 deletions.
60 changes: 52 additions & 8 deletions apps/api/src/admin/participant_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,24 @@

log = getLogger(__name__)

CheckIn: TypeAlias = tuple[datetime, str]
Checkin: TypeAlias = tuple[datetime, str]

NON_HACKER_ROLES = (
Role.MENTOR,
Role.VOLUNTEER,
Role.SPONSOR,
Role.JUDGE,
Role.WORKSHOP_LEAD,
)


class Participant(UserRecord):
"""Participants attending the event."""

checkins: list[CheckIn] = []
checkins: list[Checkin] = []
first_name: str
last_name: str
status: Union[Status, Decision]
status: Union[Status, Decision] = Status.REVIEWED


async def get_hackers() -> list[Participant]:
Expand Down Expand Up @@ -54,15 +62,29 @@ async def get_hackers() -> list[Participant]:
return [Participant(**user, **user["application_data"]) for user in records]


async def check_in_applicant(uid: str, associate: User) -> None:
"""Check in applicant at IrvineHacks"""
async def get_non_hackers() -> list[Participant]:
"""Fetch all non-hackers participating in the event."""
records: list[dict[str, Any]] = await mongodb_handler.retrieve(
Collection.USERS,
{"role": {"$in": NON_HACKER_ROLES}},
["_id", "status", "role", "checkins", "first_name", "last_name"],
)
return [Participant(**user) for user in records]


async def check_in_participant(uid: str, associate: User) -> None:
"""Check in participant at IrvineHacks"""
record: Optional[dict[str, object]] = await mongodb_handler.retrieve_one(
Collection.USERS, {"_id": uid, "role": Role.APPLICANT}
Collection.USERS, {"_id": uid, "role": {"$exists": True}}
)
if not record or record["status"] not in (Status.ATTENDING, Status.CONFIRMED):

if not record or record.get("status", "") not in (
Status.ATTENDING,
Status.CONFIRMED,
):
raise ValueError

new_checkin_entry: CheckIn = (utc_now(), associate.uid)
new_checkin_entry: Checkin = (utc_now(), associate.uid)

update_status = await mongodb_handler.raw_update_one(
Collection.USERS,
Expand All @@ -75,3 +97,25 @@ async def check_in_applicant(uid: str, associate: User) -> None:
raise RuntimeError(f"Could not update check-in record for {uid}.")

log.info(f"Applicant {uid} checked in by {associate.uid}")


async def confirm_attendance_non_hacker(uid: str, director: User) -> None:
"""Update status for Role.Attending for non-hackers."""

record: Optional[dict[str, object]] = await mongodb_handler.retrieve_one(
Collection.USERS, {"_id": uid, "status": Status.WAIVER_SIGNED}
)

if not record or record["role"] not in NON_HACKER_ROLES:
raise ValueError

update_status = await mongodb_handler.raw_update_one(
Collection.USERS,
{"_id": uid},
{"status": Status.ATTENDING},
)

if not update_status:
raise RuntimeError(f"Could not update status to ATTENDING for {uid}.")

log.info(f"Non-hacker {uid} status updated to attending by {director.uid}")
26 changes: 21 additions & 5 deletions apps/api/src/routers/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,25 +248,41 @@ async def waitlist_release(uid: str) -> None:
@router.get("/participants", dependencies=[Depends(require_checkin_associate)])
async def participants() -> list[Participant]:
"""Get list of participants."""
# TODO: non-hackers
return await participant_manager.get_hackers()
hackers = await participant_manager.get_hackers()
non_hackers = await participant_manager.get_non_hackers()
return hackers + non_hackers


@router.post("/checkin/{uid}")
async def checkin(
async def check_in_participant(
uid: str, associate: Annotated[User, Depends(require_checkin_associate)]
) -> None:
"""Check in participant at IrvineHacks."""
try:
# TODO: non-hackers
await participant_manager.check_in_applicant(uid, associate)
await participant_manager.check_in_participant(uid, associate)
except ValueError:
raise HTTPException(status.HTTP_404_NOT_FOUND)
except RuntimeError as err:
log.exception("During participant check-in: %s", err)
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)


@router.post(
"/update-attendance/{uid}",
)
async def update_attendance(
uid: str, director: Annotated[User, Depends(require_role([Role.DIRECTOR]))]
) -> None:
"""Update status to Role.ATTENDING for non-hackers."""
try:
await participant_manager.confirm_attendance_non_hacker(uid, director)
except ValueError:
raise HTTPException(status.HTTP_404_NOT_FOUND)
except RuntimeError as err:
log.exception("While updating participant attendance: %s", err)
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)


async def _process_status(uids: Sequence[str], status: Status) -> None:
ok = await mongodb_handler.update(
Collection.USERS, {"_id": {"$in": uids}}, {"status": status}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ function CheckInModal({ onDismiss, onConfirm, participant }: ActionModalProps) {
<TextContent>
<ul>
{/* TODO: actual instructions for check-in associates */}
<li>Create a badge for the participant ...</li>
<li>Ask participant to sign the SPFB sheet ...</li>
<li>Ask for a photo ID and verify name is under attendee list.</li>
<li>Have participant sign the SPFB sheet.</li>
<li>Scan badge barcode with webcam or type in digits.</li>
<li>Fill in badge and give to participant.</li>
</ul>
</TextContent>
{/* TODO: badge barcode input */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ function WaitlistPromotionModal({
<TextContent>
<ul>
{/* TODO: actual instructions for check-in leads */}
<li>Log into the portal</li>
<li>Sign waiver</li>
<li>Confirm attendance</li>
<li>Ask for a photo ID and verify name is under waitlist.</li>
<li>Promote participant.</li>
<li>
Have participant log into the portal, sign the waiver, and confirm
attendance.
</li>
<li>Follow normal check-in procedures.</li>
<li>
Direct participant to info booth for Slack and event onboarding.
</li>
</ul>
</TextContent>
{/* TODO: badge barcode input */}
Expand Down

0 comments on commit 4a75340

Please sign in to comment.