Change email function to use email address directly
This commit is contained in:
parent
31af4e933f
commit
d83f660918
Binary file not shown.
|
|
@ -0,0 +1,40 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import django
|
||||||
|
|
||||||
|
sys.path.append("../server")
|
||||||
|
|
||||||
|
os.environ.setdefault("IT_APP_ENVIRONMENT", "local")
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.base")
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from vbv_lernwelt.notify.email.email_services import (
|
||||||
|
EmailTemplate,
|
||||||
|
send_email,
|
||||||
|
create_template_data_from_course_session_attendance_course,
|
||||||
|
)
|
||||||
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("start")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
csac = CourseSessionAttendanceCourse.objects.get(pk=1)
|
||||||
|
print(csac)
|
||||||
|
print(csac.trainer)
|
||||||
|
print(csac.due_date)
|
||||||
|
|
||||||
|
result = send_email(
|
||||||
|
to_emails="daniel.egger+sendgrid@gmail.com",
|
||||||
|
template=EmailTemplate.ATTENDANCE_COURSE_REMINDER,
|
||||||
|
template_data=create_template_data_from_course_session_attendance_course(csac),
|
||||||
|
template_language="de",
|
||||||
|
fail_silently=False,
|
||||||
|
)
|
||||||
|
print(result)
|
||||||
|
|
@ -30,6 +30,7 @@ django-debug-toolbar # https://github.com/jazzband/django-debug-toolbar
|
||||||
django-extensions # https://github.com/django-extensions/django-extensions
|
django-extensions # https://github.com/django-extensions/django-extensions
|
||||||
django-coverage-plugin # https://github.com/nedbat/django_coverage_plugin
|
django-coverage-plugin # https://github.com/nedbat/django_coverage_plugin
|
||||||
pytest-django # https://github.com/pytest-dev/pytest-django
|
pytest-django # https://github.com/pytest-dev/pytest-django
|
||||||
|
freezegun # https://github.com/spulec/freezegun
|
||||||
|
|
||||||
# django-watchfiles custom PR
|
# django-watchfiles custom PR
|
||||||
https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,8 @@ flake8==6.1.0
|
||||||
# flake8-isort
|
# flake8-isort
|
||||||
flake8-isort==6.0.0
|
flake8-isort==6.0.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
|
freezegun==1.2.2
|
||||||
|
# via -r requirements-dev.in
|
||||||
gitdb==4.0.10
|
gitdb==4.0.10
|
||||||
# via gitdb2
|
# via gitdb2
|
||||||
gitdb2==4.0.2
|
gitdb2==4.0.2
|
||||||
|
|
@ -409,6 +411,7 @@ python-dateutil==2.8.2
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# botocore
|
# botocore
|
||||||
# faker
|
# faker
|
||||||
|
# freezegun
|
||||||
python-dotenv==1.0.0
|
python-dotenv==1.0.0
|
||||||
# via
|
# via
|
||||||
# environs
|
# environs
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.core.utils import find_first
|
from vbv_lernwelt.core.utils import find_first
|
||||||
from vbv_lernwelt.course.models import CourseCompletionStatus, CourseSession
|
from vbv_lernwelt.course.models import CourseCompletionStatus, CourseSession
|
||||||
from vbv_lernwelt.course.services import mark_course_completion
|
from vbv_lernwelt.course.services import mark_course_completion
|
||||||
from vbv_lernwelt.notify.service import EmailTemplate, NotificationService
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate
|
||||||
|
from vbv_lernwelt.notify.services import NotificationService
|
||||||
|
|
||||||
|
|
||||||
def update_assignment_completion(
|
def update_assignment_completion(
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.models import CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
from vbv_lernwelt.notify.service import EmailTemplate, NotificationService
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate
|
||||||
|
from vbv_lernwelt.notify.services import NotificationService
|
||||||
|
|
||||||
|
|
||||||
class FeedbackIntegerField(models.IntegerField):
|
class FeedbackIntegerField(models.IntegerField):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
import structlog
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from sendgrid import Mail, SendGridAPIClient
|
||||||
|
|
||||||
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
|
|
||||||
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
DATETIME_FORMAT_SWISS_STR = "%d.%m.%Y %H:%M"
|
||||||
|
|
||||||
|
|
||||||
|
def format_swiss_datetime(dt: timezone.datetime) -> str:
|
||||||
|
return dt.astimezone(timezone.get_current_timezone()).strftime(
|
||||||
|
DATETIME_FORMAT_SWISS_STR
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EmailTemplate(Enum):
|
||||||
|
"""Enum for the different Sendgrid email templates."""
|
||||||
|
|
||||||
|
# VBV - Erinnerung Präsenzkurse
|
||||||
|
ATTENDANCE_COURSE_REMINDER = {
|
||||||
|
"de": "d-9af079f98f524d85ac6e4166de3480da",
|
||||||
|
"it": "d-ab78ddca8a7a46b8afe50aaba3efee81",
|
||||||
|
"fr": "d-f88d9912e5484e55a879571463e4a166",
|
||||||
|
}
|
||||||
|
|
||||||
|
# VBV - Geleitete Fallarbeit abgegeben
|
||||||
|
CASEWORK_SUBMITTED = {"de": "d-599f0b35ddcd4fac99314cdf8f5446a2"}
|
||||||
|
|
||||||
|
# VBV - Geleitete Fallarbeit bewertet
|
||||||
|
CASEWORK_EVALUATED = {"de": "d-8c57fa13116b47be8eec95dfaf2aa030"}
|
||||||
|
|
||||||
|
# VBV - Neues Feedback für Circle
|
||||||
|
NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"}
|
||||||
|
|
||||||
|
|
||||||
|
def send_email(
|
||||||
|
to_emails: str | list[str],
|
||||||
|
template: EmailTemplate,
|
||||||
|
template_data: dict,
|
||||||
|
template_language: str = "de",
|
||||||
|
fail_silently: bool = True,
|
||||||
|
) -> bool:
|
||||||
|
log = logger.bind(
|
||||||
|
recipient_emails=to_emails,
|
||||||
|
template=template.name,
|
||||||
|
template_data=template_data,
|
||||||
|
template_language=template_language,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
send_sendgrid_email(
|
||||||
|
to_emails=to_emails,
|
||||||
|
template=template,
|
||||||
|
template_data=template_data,
|
||||||
|
template_language=template_language,
|
||||||
|
)
|
||||||
|
log.info("Email sent successfully")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
log.error(
|
||||||
|
"Failed to send Email", exception=str(e), exc_info=True, stack_info=True
|
||||||
|
)
|
||||||
|
if not fail_silently:
|
||||||
|
raise e
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def send_sendgrid_email(
|
||||||
|
to_emails: str | list[str],
|
||||||
|
template: EmailTemplate,
|
||||||
|
template_data: dict,
|
||||||
|
template_language: str = "de",
|
||||||
|
) -> None:
|
||||||
|
message = Mail(
|
||||||
|
from_email="noreply@my.vbv-afa.ch",
|
||||||
|
to_emails=to_emails,
|
||||||
|
)
|
||||||
|
message.template_id = template.value.get(template_language, template.value["de"])
|
||||||
|
message.dynamic_template_data = template_data
|
||||||
|
SendGridAPIClient(settings.SENDGRID_API_KEY).send(message)
|
||||||
|
|
||||||
|
|
||||||
|
def create_template_data_from_course_session_attendance_course(
|
||||||
|
attendance_course: CourseSessionAttendanceCourse,
|
||||||
|
):
|
||||||
|
return {
|
||||||
|
"attendance_course": attendance_course.learning_content.title,
|
||||||
|
"location": attendance_course.location,
|
||||||
|
"trainer": attendance_course.trainer,
|
||||||
|
"start": format_swiss_datetime(attendance_course.due_date.start),
|
||||||
|
"end": format_swiss_datetime(attendance_course.due_date.end),
|
||||||
|
}
|
||||||
|
|
@ -8,19 +8,18 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.models import CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
from vbv_lernwelt.notify.service import EmailTemplate, NotificationService
|
from vbv_lernwelt.notify.email.email_services import (
|
||||||
|
create_template_data_from_course_session_attendance_course,
|
||||||
|
EmailTemplate,
|
||||||
|
)
|
||||||
|
from vbv_lernwelt.notify.services import NotificationService
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
PRESENCE_COURSE_REMINDER_LEAD_TIME = timedelta(weeks=2)
|
PRESENCE_COURSE_REMINDER_LEAD_TIME = timedelta(weeks=2)
|
||||||
DATETIME_FORMAT_STR = "%H:%M %d.%m.%Y"
|
|
||||||
|
|
||||||
|
|
||||||
def format_datetime(dt: timezone.datetime) -> str:
|
def send_attendance_course_reminder_notification(
|
||||||
return dt.astimezone(timezone.get_current_timezone()).strftime(DATETIME_FORMAT_STR)
|
|
||||||
|
|
||||||
|
|
||||||
def send_notification(
|
|
||||||
recipient: User, attendance_course: CourseSessionAttendanceCourse
|
recipient: User, attendance_course: CourseSessionAttendanceCourse
|
||||||
):
|
):
|
||||||
NotificationService.send_information_notification(
|
NotificationService.send_information_notification(
|
||||||
|
|
@ -28,24 +27,20 @@ def send_notification(
|
||||||
verb=_("Erinnerung: Bald findet ein Präsenzkurs statt"),
|
verb=_("Erinnerung: Bald findet ein Präsenzkurs statt"),
|
||||||
target_url=attendance_course.learning_content.get_frontend_url(),
|
target_url=attendance_course.learning_content.get_frontend_url(),
|
||||||
email_template=EmailTemplate.ATTENDANCE_COURSE_REMINDER,
|
email_template=EmailTemplate.ATTENDANCE_COURSE_REMINDER,
|
||||||
template_data={
|
template_data=create_template_data_from_course_session_attendance_course(
|
||||||
"attendance_course": attendance_course.learning_content.title,
|
attendance_course=attendance_course
|
||||||
"location": attendance_course.location,
|
),
|
||||||
"trainer": attendance_course.trainer,
|
|
||||||
"start": format_datetime(attendance_course.due_date.start),
|
|
||||||
"end": format_datetime(attendance_course.due_date.end),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def check_attendance_course():
|
def attendance_course_reminder_notification_job():
|
||||||
"""Checks if an attendance course is coming up and sends a reminder to the participants"""
|
"""Checks if an attendance course is coming up and sends a reminder to the participants"""
|
||||||
start = timezone.now()
|
start = timezone.now()
|
||||||
end = timezone.now() + PRESENCE_COURSE_REMINDER_LEAD_TIME
|
end = timezone.now() + PRESENCE_COURSE_REMINDER_LEAD_TIME
|
||||||
logger.info(
|
logger.info(
|
||||||
"Querying for attendance courses in specified time range",
|
"Querying for attendance courses in specified time range",
|
||||||
start_time=start.strftime(DATETIME_FORMAT_STR),
|
start_time=start,
|
||||||
end_time=end.strftime(DATETIME_FORMAT_STR),
|
end_time=end,
|
||||||
)
|
)
|
||||||
attendance_courses = CourseSessionAttendanceCourse.objects.filter(
|
attendance_courses = CourseSessionAttendanceCourse.objects.filter(
|
||||||
due_date__start__lte=end,
|
due_date__start__lte=end,
|
||||||
|
|
@ -55,11 +50,11 @@ def check_attendance_course():
|
||||||
cs_id = attendance_course.course_session.id
|
cs_id = attendance_course.course_session.id
|
||||||
csu = CourseSessionUser.objects.filter(course_session_id=cs_id)
|
csu = CourseSessionUser.objects.filter(course_session_id=cs_id)
|
||||||
for user in csu:
|
for user in csu:
|
||||||
send_notification(user.user, attendance_course)
|
send_attendance_course_reminder_notification(user.user, attendance_course)
|
||||||
if not attendance_courses:
|
if not attendance_courses:
|
||||||
logger.info("No attendance courses found")
|
logger.info("No attendance courses found")
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
def command():
|
def command():
|
||||||
check_attendance_course()
|
attendance_course_reminder_notification_job()
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,15 @@
|
||||||
from enum import Enum
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
from notifications.signals import notify
|
from notifications.signals import notify
|
||||||
from sendgrid import Mail, SendGridAPIClient
|
|
||||||
from storages.utils import setting
|
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate, send_email
|
||||||
from vbv_lernwelt.notify.models import Notification, NotificationType
|
from vbv_lernwelt.notify.models import Notification, NotificationType
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class EmailTemplate(Enum):
|
|
||||||
"""Enum for the different Sendgrid email templates."""
|
|
||||||
|
|
||||||
# VBV - Erinnerung Präsenzkurse
|
|
||||||
ATTENDANCE_COURSE_REMINDER = {
|
|
||||||
"de": "d-9af079f98f524d85ac6e4166de3480da",
|
|
||||||
"it": "d-ab78ddca8a7a46b8afe50aaba3efee81",
|
|
||||||
"fr": "d-f88d9912e5484e55a879571463e4a166",
|
|
||||||
}
|
|
||||||
|
|
||||||
# VBV - Geleitete Fallarbeit abgegeben
|
|
||||||
CASEWORK_SUBMITTED = {"de": "d-599f0b35ddcd4fac99314cdf8f5446a2"}
|
|
||||||
|
|
||||||
# VBV - Geleitete Fallarbeit bewertet
|
|
||||||
CASEWORK_EVALUATED = {"de": "d-8c57fa13116b47be8eec95dfaf2aa030"}
|
|
||||||
|
|
||||||
# VBV - Neues Feedback für Circle
|
|
||||||
NEW_FEEDBACK = {"de": "d-40fb94d5149949e7b8e7ddfcf0fcfdde"}
|
|
||||||
|
|
||||||
|
|
||||||
class EmailService:
|
|
||||||
"""Email service class implemented using the Sendgrid API"""
|
|
||||||
|
|
||||||
_sendgrid_client = SendGridAPIClient(setting("SENDGRID_API_KEY"))
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def send_email(
|
|
||||||
cls,
|
|
||||||
recipient: User,
|
|
||||||
template: EmailTemplate,
|
|
||||||
template_data: dict,
|
|
||||||
) -> None:
|
|
||||||
message = Mail(
|
|
||||||
from_email="noreply@my.vbv-afa.ch",
|
|
||||||
to_emails=recipient.email,
|
|
||||||
)
|
|
||||||
message.template_id = template.value.get(
|
|
||||||
recipient.language, template.value["de"]
|
|
||||||
)
|
|
||||||
message.dynamic_template_data = template_data
|
|
||||||
cls._sendgrid_client.send(message)
|
|
||||||
|
|
||||||
|
|
||||||
class NotificationService:
|
class NotificationService:
|
||||||
@classmethod
|
@classmethod
|
||||||
def send_user_interaction_notification(
|
def send_user_interaction_notification(
|
||||||
|
|
@ -153,7 +108,7 @@ class NotificationService:
|
||||||
template_name=email_template.name,
|
template_name=email_template.name,
|
||||||
template_data=template_data,
|
template_data=template_data,
|
||||||
):
|
):
|
||||||
log.warn("A duplicate notification was omitted from being sent")
|
log.info("A duplicate notification was omitted from being sent")
|
||||||
return
|
return
|
||||||
|
|
||||||
emailed = False
|
emailed = False
|
||||||
|
|
@ -200,26 +155,14 @@ class NotificationService:
|
||||||
def _send_email(
|
def _send_email(
|
||||||
recipient: User,
|
recipient: User,
|
||||||
template: EmailTemplate,
|
template: EmailTemplate,
|
||||||
template_data: dict | None,
|
template_data: dict,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
log = logger.bind(
|
return send_email(
|
||||||
recipient=recipient.username,
|
to_emails=recipient.email,
|
||||||
template=template.name,
|
template=template,
|
||||||
template_data=template_data,
|
template_data=template_data,
|
||||||
|
template_language=recipient.language,
|
||||||
)
|
)
|
||||||
try:
|
|
||||||
EmailService.send_email(
|
|
||||||
recipient=recipient,
|
|
||||||
template=template,
|
|
||||||
template_data=template_data,
|
|
||||||
)
|
|
||||||
log.info("Email sent successfully")
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
log.error(
|
|
||||||
"Failed to send Email", exception=str(e), exc_info=True, stack_info=True
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _is_duplicate_notification(
|
def _is_duplicate_notification(
|
||||||
|
|
@ -6,6 +6,7 @@ from django.contrib.auth.models import User
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from vbv_lernwelt.core.constants import TEST_COURSE_SESSION_BERN_ID
|
from vbv_lernwelt.core.constants import TEST_COURSE_SESSION_BERN_ID
|
||||||
from vbv_lernwelt.core.create_default_users import create_default_users
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
|
|
@ -13,10 +14,10 @@ from vbv_lernwelt.course.creators.test_course import create_test_course
|
||||||
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||||
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
from vbv_lernwelt.learnpath.models import LearningContentAttendanceCourse
|
from vbv_lernwelt.learnpath.models import LearningContentAttendanceCourse
|
||||||
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate
|
||||||
from vbv_lernwelt.notify.management.commands.send_attendance_course_reminders import (
|
from vbv_lernwelt.notify.management.commands.send_attendance_course_reminders import (
|
||||||
check_attendance_course,
|
attendance_course_reminder_notification_job,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.notify.service import EmailTemplate
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -36,7 +37,7 @@ def on_send_notification(**kwargs) -> None:
|
||||||
|
|
||||||
|
|
||||||
@patch(
|
@patch(
|
||||||
"vbv_lernwelt.notify.service.NotificationService.send_information_notification",
|
"vbv_lernwelt.notify.services.NotificationService.send_information_notification",
|
||||||
on_send_notification,
|
on_send_notification,
|
||||||
)
|
)
|
||||||
class TestAttendanceCourseReminders(TestCase):
|
class TestAttendanceCourseReminders(TestCase):
|
||||||
|
|
@ -75,6 +76,9 @@ class TestAttendanceCourseReminders(TestCase):
|
||||||
location="Handelsschule BV Bern, Zimmer 122",
|
location="Handelsschule BV Bern, Zimmer 122",
|
||||||
trainer="Thomas Berger",
|
trainer="Thomas Berger",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@freeze_time("2023-08-25 13:02:01")
|
||||||
|
def test_happy_day(self):
|
||||||
in_two_weeks = datetime.now() + timedelta(weeks=2, days=1)
|
in_two_weeks = datetime.now() + timedelta(weeks=2, days=1)
|
||||||
self.csac_future.due_date.start = timezone.make_aware(
|
self.csac_future.due_date.start = timezone.make_aware(
|
||||||
in_two_weeks.replace(hour=5, minute=20, second=0, microsecond=0)
|
in_two_weeks.replace(hour=5, minute=20, second=0, microsecond=0)
|
||||||
|
|
@ -84,8 +88,7 @@ class TestAttendanceCourseReminders(TestCase):
|
||||||
)
|
)
|
||||||
self.csac_future.due_date.save()
|
self.csac_future.due_date.save()
|
||||||
|
|
||||||
def test_happy_day(self):
|
attendance_course_reminder_notification_job()
|
||||||
check_attendance_course()
|
|
||||||
self.assertEquals(3, len(sent_notifications))
|
self.assertEquals(3, len(sent_notifications))
|
||||||
recipients = CourseSessionUser.objects.filter(
|
recipients = CourseSessionUser.objects.filter(
|
||||||
course_session_id=self.csac.course_session.id
|
course_session_id=self.csac.course_session.id
|
||||||
|
|
@ -94,6 +97,7 @@ class TestAttendanceCourseReminders(TestCase):
|
||||||
set(map(lambda n: n.recipient, sent_notifications)),
|
set(map(lambda n: n.recipient, sent_notifications)),
|
||||||
set(map(lambda csu: csu.user, recipients)),
|
set(map(lambda csu: csu.user, recipients)),
|
||||||
)
|
)
|
||||||
|
|
||||||
for notification in sent_notifications:
|
for notification in sent_notifications:
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
_("Erinnerung: Bald findet ein Präsenzkurs statt"),
|
_("Erinnerung: Bald findet ein Präsenzkurs statt"),
|
||||||
|
|
@ -116,10 +120,10 @@ class TestAttendanceCourseReminders(TestCase):
|
||||||
notification.template_data["trainer"],
|
notification.template_data["trainer"],
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
self.csac.due_date.start.strftime("%H:%M %d.%m.%Y"),
|
self.csac.due_date.start.strftime("%d.%m.%Y %H:%M"),
|
||||||
notification.template_data["start"],
|
notification.template_data["start"],
|
||||||
)
|
)
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
self.csac.due_date.end.strftime("%H:%M %d.%m.%Y"),
|
self.csac.due_date.end.strftime("%d.%m.%Y %H:%M"),
|
||||||
notification.template_data["end"],
|
notification.template_data["end"],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ from django.test import TestCase
|
||||||
|
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.core.tests.factories import UserFactory
|
from vbv_lernwelt.core.tests.factories import UserFactory
|
||||||
|
from vbv_lernwelt.notify.email.email_services import EmailTemplate
|
||||||
from vbv_lernwelt.notify.models import Notification, NotificationType
|
from vbv_lernwelt.notify.models import Notification, NotificationType
|
||||||
from vbv_lernwelt.notify.service import EmailTemplate, NotificationService
|
from vbv_lernwelt.notify.services import NotificationService
|
||||||
|
|
||||||
|
|
||||||
class TestNotificationService(TestCase):
|
class TestNotificationService(TestCase):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue