Skip to content
Open
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
30 changes: 16 additions & 14 deletions dailyClassReminder.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import json
import datetime
import logging
from collections import defaultdict

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
Expand Down Expand Up @@ -78,27 +79,28 @@ def get_teacher_contact_info():
def main():
TEACHER_EMAILS = get_teacher_contact_info()
RESPONSE_EVENTS = get_response_events(SEARCH_FIELDS, OUTPUT_FIELDS)
CLASSES = defaultdict(list)
for item in RESPONSE_EVENTS["searchResults"]:
teacher = item["Event Topic"] or "Unassigned"
CLASSES[teacher].append(item)

# Remove duplicates in the list of teachers
TEACHERS = {item.get("Event Topic") for item in RESPONSE_EVENTS["searchResults"]}

for teacher in TEACHERS:
for teacher, events in CLASSES.items():
try:
if not teacher:
logging.info("WARNING: No teacher assigned!")
# Handle events with no teacher assigned
if not teacher or teacher == "Unassigned":
teacher_display = "Unassigned Teacher"
class_names = ', '.join([event['Event Name'] for event in events])
logging.info("WARNING: No teacher assigned for classes: %s", class_names)
TEACHER_EMAILS[teacher] = "classes@asmbly.org"
else:
teacher_display = teacher

if teacher in ALREADY_SENT:
logging.info("Already emailed %s", teacher)
logging.info("Already emailed %s", teacher_display)
continue

# Find all events for each teacher
events = list(
filter(
lambda x, teach=teacher: x["Event Topic"] == teach,
RESPONSE_EVENTS["searchResults"],
)
)
logging.info("\n\n_____\n\nEmailing %s about %s event(s)...", teacher, len(events))
logging.info("\n\n_____\n\nEmailing %s about %s event(s)...", teacher_display, len(events))
sorted_events = sorted(
events, key=lambda x: datetime.datetime.fromisoformat(x["Event Start Date"])
)
Expand Down
25 changes: 25 additions & 0 deletions tests/test_dailyClassReminders.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def test_email_includes_registrant_details(
# Verify event search API was called
assert search_mock.called

assert self.mock_smtp.send_message.call_count == 1
email_message = self.mock_smtp.send_message.call_args[0][0]
email_body = email_message.as_string()

Expand Down Expand Up @@ -187,3 +188,27 @@ def test_canceled_registrants_not_included(

assert f"{good_student.firstName} {good_student.lastName}" in email_body
assert f"{canceled_student.firstName} {canceled_student.lastName}" not in email_body

def test_none_teacher_sends_to_classes_email(
self, requests_mock, mock_teachers_file
):
"""Test that events with None as teacher are handled properly"""
student = NeonUserMock()
event = NeonEventMock(event_name="Orphaned Class", teacher=None).add_registrant(student)

search_mock, _ = NeonEventMock.mock_events(requests_mock, [event])

import dailyClassReminder
dailyClassReminder.main()

# Verify event search API was called
assert search_mock.called

# Should still send email
assert self.mock_smtp.send_message.call_count == 1

# Email should go to classes@asmbly.org
email_message = self.mock_smtp.send_message.call_args[0][0]
assert email_message["To"] == "classes@asmbly.org"