diff --git a/server/vbv_lernwelt/notify/email/email_services.py b/server/vbv_lernwelt/notify/email/email_services.py index 525133d5..66cb7b97 100644 --- a/server/vbv_lernwelt/notify/email/email_services.py +++ b/server/vbv_lernwelt/notify/email/email_services.py @@ -29,22 +29,28 @@ class EmailTemplate(Enum): "fr": "d-f88d9912e5484e55a879571463e4a166", } - # FIXME: Create Sendgrid templates - # Assumption: Edonqic, CaseWork and PrepAssignment share - # the same template for now. Once the templates are created - # update the template ids here and make sure the needed template - # data is passed to _send_notification! - ASSIGNMENT_REMINDER = { - "de": "", - "it": "", - "fr": "", + ASSIGNMENT_REMINDER_CASEWORK_MEMBER = { + "de": "d-8b84fd96213540a796c40d4344bc606f", + "fr": "d-ae6cd87b6b574643b4fff209148c7620", + "it": "d-1bf8b12a70324e1b91050d5fa01ed81f", } - # FIXME: Same as above... - CASEWORK_EXPERT_EVALUATION_REMINDER = { - "de": "", - "it": "", - "fr": "", + ASSIGNMENT_REMINDER_PREP_ASSIGNMENT_MEMBER = { + "de": "d-cb866d8c538f4ffaab923022ef7209fa", + "fr": "d-fdc84ae0e1b7417a8ede8db4e07ee7a8", + "it": "d-39d16586341b4559b3a3df71db3d04fb", + } + + ASSIGNMENT_REMINDER_EDONIQ_MEMBER = { + "de": "d-4b26911d04834079a64ab1758ca470cc", + "fr": "d-b9f27e3e13e44f20aa5d1a40c93da00d", + "it": "d-1d3d854c5b3e4012ac3d33eeb3d6e7d1", + } + + EVALUATION_REMINDER_CASEWORK_EXPERT = { + "de": "d-6e3dd4acc7fc4ce7a2776f5147bd32fd", + "fr": "d-0104add90a354d7fb1fc9fecfa132d06", + "it": "d-630e9316960647768c0a657e175436aa", } # VBV - Geleitete Fallarbeit abgegeben diff --git a/server/vbv_lernwelt/notify/management/commands/send_assigment_course_reminders.py b/server/vbv_lernwelt/notify/management/commands/send_assigment_course_reminders.py index 5cb5c59f..468c49d2 100644 --- a/server/vbv_lernwelt/notify/management/commands/send_assigment_course_reminders.py +++ b/server/vbv_lernwelt/notify/management/commands/send_assigment_course_reminders.py @@ -36,23 +36,23 @@ def assignment_reminder_members_notification_job(): role=CourseSessionUser.Role.MEMBER, ): sent.append( - NotificationService.send_assignment_reminder_notification( - member.user, assignment + NotificationService.send_assignment_reminder_notification_member( + recipient=member.user, assignment=assignment ) ) # member notifications (EDONIQ_TEST) - for assignment in CourseSessionEdoniqTest.objects.filter( + for edoniq_test in CourseSessionEdoniqTest.objects.filter( deadline__start__lte=end, deadline__start__gte=start, ): for member in CourseSessionUser.objects.filter( - course_session_id=assignment.course_session.id, + course_session_id=edoniq_test.course_session.id, role=CourseSessionUser.Role.MEMBER, ): sent.append( - NotificationService.send_assignment_reminder_notification( - member.user, assignment + NotificationService.send_edoniq_test_reminder_notification_member( + recipient=member.user, edoniq_test=edoniq_test ) ) @@ -70,7 +70,7 @@ def assignment_reminder_members_notification_job(): ): sent.append( NotificationService.send_casework_expert_evaluation_reminder( - expert.user, assignment + recipient=expert.user, assignment=assignment ) ) diff --git a/server/vbv_lernwelt/notify/services.py b/server/vbv_lernwelt/notify/services.py index 3239754e..48649c72 100644 --- a/server/vbv_lernwelt/notify/services.py +++ b/server/vbv_lernwelt/notify/services.py @@ -1,17 +1,22 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING import structlog from django.db.models import Model from notifications.signals import notify +from vbv_lernwelt.assignment.models import AssignmentType from vbv_lernwelt.core.models import User from vbv_lernwelt.course.models import CourseSession +from vbv_lernwelt.course_session.models import ( + CourseSessionAssignment, +) from vbv_lernwelt.notify.email.email_services import ( create_template_data_from_course_session_attendance_course, EmailTemplate, send_email, + format_swiss_datetime, ) from vbv_lernwelt.notify.models import ( Notification, @@ -22,7 +27,6 @@ from vbv_lernwelt.notify.models import ( if TYPE_CHECKING: from vbv_lernwelt.assignment.models import AssignmentCompletion from vbv_lernwelt.course_session.models import ( - CourseSessionAssignment, CourseSessionAttendanceCourse, CourseSessionEdoniqTest, ) @@ -142,17 +146,25 @@ class NotificationService: ) @classmethod - def send_assignment_reminder_notification( + def send_assignment_reminder_notification_member( cls, recipient: User, - assignment: Union[CourseSessionAssignment, CourseSessionEdoniqTest], + assignment: CourseSessionAssignment, ): texts = { "de": "Erinnerung: Bald ist ein Abgabetermin", "fr": "Rappel: Une date limite approche", "it": "Promemoria: Una scadenza si avvicina", } + + templates = { + AssignmentType.CASEWORK: EmailTemplate.ASSIGNMENT_REMINDER_CASEWORK_MEMBER, + AssignmentType.PREP_ASSIGNMENT: EmailTemplate.ASSIGNMENT_REMINDER_PREP_ASSIGNMENT_MEMBER, + } + verb = texts.get(recipient.language, "de") + circle = assignment.learning_content.get_parent_circle().title + due_at = assignment.submission_deadline.start return cls._send_notification( recipient=recipient, @@ -162,10 +174,43 @@ class NotificationService: target_url=assignment.learning_content.get_frontend_url(), action_object=assignment, course_session=assignment.course_session, - email_template=EmailTemplate.ASSIGNMENT_REMINDER, + email_template=templates[ + AssignmentType(assignment.learning_content.assignment_type) + ], template_data={ - # FIXME: Add template data as needed - # for the sendgrid email template + "circle": circle, + "due_date": format_swiss_datetime(due_at), + }, + ) + + @classmethod + def send_edoniq_test_reminder_notification_member( + cls, + recipient: User, + edoniq_test: CourseSessionEdoniqTest, + ): + texts = { + "de": "Erinnerung: Bald ist ein Abgabetermin", + "fr": "Rappel: Une date limite approche", + "it": "Promemoria: Una scadenza si avvicina", + } + + verb = texts.get(recipient.language, "de") + circle = edoniq_test.learning_content.get_parent_circle().title + due_at = edoniq_test.deadline.start + + return cls._send_notification( + recipient=recipient, + verb=verb, + notification_category=NotificationCategory.INFORMATION, + notification_trigger=NotificationTrigger.ASSIGNMENT_REMINDER, + target_url=edoniq_test.learning_content.get_frontend_url(), + action_object=edoniq_test, + course_session=edoniq_test.course_session, + email_template=EmailTemplate.ASSIGNMENT_REMINDER_EDONIQ_MEMBER, + template_data={ + "circle": circle, + "due_date": format_swiss_datetime(due_at), }, ) @@ -180,7 +225,10 @@ class NotificationService: "fr": "Rappel: Une date limite approche", "it": "Promemoria: Una scadenza si avvicina", } + verb = texts.get(recipient.language, "de") + circle = assignment.learning_content.get_parent_circle().title + due_at = assignment.evaluation_deadline.start return cls._send_notification( recipient=recipient, @@ -190,10 +238,10 @@ class NotificationService: target_url=assignment.evaluation_deadline.url_expert, action_object=assignment, course_session=assignment.course_session, - email_template=EmailTemplate.CASEWORK_EXPERT_EVALUATION_REMINDER, + email_template=EmailTemplate.EVALUATION_REMINDER_CASEWORK_EXPERT, template_data={ - # FIXME: Add template data as needed - # for the sendgrid email template + "circle": circle, + "due_date": format_swiss_datetime(due_at), }, ) diff --git a/server/vbv_lernwelt/notify/tests/test_send_assigment_course_reminders.py b/server/vbv_lernwelt/notify/tests/test_send_assigment_course_reminders.py index c8fef4b1..de5e2736 100644 --- a/server/vbv_lernwelt/notify/tests/test_send_assigment_course_reminders.py +++ b/server/vbv_lernwelt/notify/tests/test_send_assigment_course_reminders.py @@ -1,3 +1,4 @@ +import re from datetime import datetime from typing import Dict @@ -18,6 +19,7 @@ from vbv_lernwelt.learnpath.models import ( LearningContentAssignment, LearningContentEdoniqTest, ) +from vbv_lernwelt.notify.email.email_services import EmailTemplate from vbv_lernwelt.notify.management.commands.send_assigment_course_reminders import ( assignment_reminder_members_notification_job, ) @@ -110,6 +112,50 @@ class TestAssignmentCourseRemindersTest(TestCase): self.assertEquals("INFORMATION", notification.notification_category) self.assertEquals(EXPECTED_MEMBER_VERB, notification.verb) + template_data = notification.data["template_data"] + + self.assertEquals( + action_object.learning_content.get_parent_circle().title, + template_data["circle"], + ) + + self.assertEquals( + action_object.learning_content.get_frontend_url(), + notification.target_url, + ) + + match = re.fullmatch( + r"\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}", template_data["due_date"] + ) + + self.assertIsNotNone( + match, f"due_date format is incorrect: {template_data['due_date']}" + ) + + email_template = notification.data["email_template"] + + # make sure we have the correct email template + if type(action_object) == CourseSessionAssignment: + assignment_type = AssignmentType( + action_object.learning_content.assignment_type + ) + + if assignment_type == AssignmentType.CASEWORK: + self.assertEquals( + EmailTemplate.ASSIGNMENT_REMINDER_CASEWORK_MEMBER.name, + email_template, + ) + elif assignment_type == AssignmentType.PREP_ASSIGNMENT: + self.assertEquals( + EmailTemplate.ASSIGNMENT_REMINDER_PREP_ASSIGNMENT_MEMBER.name, + email_template, + ) + elif type(action_object) == CourseSessionEdoniqTest: + self.assertEquals( + EmailTemplate.ASSIGNMENT_REMINDER_EDONIQ_MEMBER.name, + email_template, + ) + @freeze_time("2023-01-01") def test_notification_edoniq(self): # GIVEN