Skip to content

Commit 8d751e3

Browse files
authored
feat: rsvp reminder route (#298)
* feat: rsvp reminder route * fix: mypy types and docstring * fix: application.first_name key access * feat: add log message to rsvp-reminder route
1 parent 2d6da4a commit 8d751e3

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

apps/api/src/routers/admin.py

+30-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
from auth.authorization import require_role
1010
from auth.user_identity import User, utc_now
1111
from models.ApplicationData import Decision, Review
12-
from services import mongodb_handler
12+
from services import mongodb_handler, sendgrid_handler
1313
from services.mongodb_handler import BaseRecord, Collection
14+
from services.sendgrid_handler import ApplicationUpdatePersonalization, Template
1415
from utils import email_handler
1516
from utils.batched import batched
17+
from utils.email_handler import IH_SENDER, REPLY_TO_HACK_AT_UCI
1618
from utils.user_record import Applicant, Role, Status
1719

1820
log = getLogger(__name__)
@@ -131,6 +133,33 @@ async def release_decisions() -> None:
131133
)
132134

133135

136+
@router.post("/rsvp-reminder", dependencies=[Depends(require_role([Role.DIRECTOR]))])
137+
async def rsvp_reminder() -> None:
138+
"""Send email to applicants who have a status of ACCEPTED or WAIVER_SIGNED
139+
reminding them to RSVP."""
140+
# TODO: Consider using Pydantic model validation instead of type annotations
141+
not_yet_rsvpd: list[dict[str, Any]] = await mongodb_handler.retrieve(
142+
Collection.USERS,
143+
{"status": {"$in": [Decision.ACCEPTED, Status.WAIVER_SIGNED]}},
144+
["_id", "application_data.first_name"],
145+
)
146+
log.info(f"Sending RSVP reminder emails to {len(not_yet_rsvpd)} applicants")
147+
personalizations = [
148+
ApplicationUpdatePersonalization(
149+
email=_recover_email_from_uid(record["_id"]),
150+
first_name=record["application_data"]["first_name"],
151+
)
152+
for record in not_yet_rsvpd
153+
]
154+
await sendgrid_handler.send_email(
155+
Template.RSVP_REMINDER,
156+
IH_SENDER,
157+
personalizations,
158+
True,
159+
reply_to=REPLY_TO_HACK_AT_UCI,
160+
)
161+
162+
134163
async def _process_batch(batch: tuple[dict[str, Any], ...], decision: Decision) -> None:
135164
uids: list[str] = [record["_id"] for record in batch]
136165
log.info(f"Setting {','.join(uids)} as {decision}")

apps/api/src/services/sendgrid_handler.py

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class Template(str, Enum):
2121
WAITLISTED_EMAIL = "d-9178c043de134a71a4fdbe513d35f89f"
2222
REJECTED_EMAIL = "d-71ef30ac91a941e0893b7680928d80b7"
2323
WAITLIST_RELEASE_EMAIL = "d-19af50295ac14e82a7810791a175b8e9"
24+
RSVP_REMINDER = "d-0c2642268c404c138359ac1b9d41e78c"
2425

2526

2627
class PersonalizationData(TypedDict):

0 commit comments

Comments
 (0)