-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from maykinmedia/feature/8-configure-email-not…
…ifications Configure email notifications
- Loading branch information
Showing
15 changed files
with
292 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
from datetime import datetime | ||
from unittest.mock import patch | ||
|
||
from django.core import mail | ||
from django.test import TestCase | ||
|
@@ -13,6 +14,7 @@ | |
from openarchiefbeheer.destruction.api.serializers import DestructionListSerializer | ||
from openarchiefbeheer.destruction.constants import ListItemStatus | ||
from openarchiefbeheer.destruction.tests.factories import DestructionListItemFactory | ||
from openarchiefbeheer.emails.models import EmailConfig | ||
|
||
factory = APIRequestFactory() | ||
|
||
|
@@ -57,7 +59,15 @@ def test_create_destruction_list(self): | |
|
||
self.assertTrue(serializer.is_valid()) | ||
|
||
with freeze_time("2024-05-02T16:00:00+02:00"): | ||
with ( | ||
patch( | ||
"openarchiefbeheer.emails.utils.EmailConfig.get_solo", | ||
return_value=EmailConfig( | ||
subject_review_required="Destruction list review request" | ||
), | ||
), | ||
freeze_time("2024-05-02T16:00:00+02:00"), | ||
): | ||
destruction_list = serializer.save() | ||
|
||
assignees = destruction_list.assignees.order_by("order") | ||
|
@@ -86,7 +96,7 @@ def test_create_destruction_list(self): | |
sent_mail = mail.outbox | ||
|
||
self.assertEqual(len(sent_mail), 1) | ||
self.assertEqual(sent_mail[0].subject, _("Destruction list review request")) | ||
self.assertEqual(sent_mail[0].subject, "Destruction list review request") | ||
self.assertEqual(sent_mail[0].recipients(), ["[email protected]"]) | ||
|
||
logs = TimelineLog.objects.filter(user=record_manager) | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from django.contrib import admin | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from solo.admin import SingletonModelAdmin | ||
|
||
from .models import EmailConfig | ||
|
||
|
||
@admin.register(EmailConfig) | ||
class EmailConfigAdmin(SingletonModelAdmin): | ||
fieldsets = [ | ||
( | ||
_("Template review request"), | ||
{ | ||
"fields": ["subject_review_required", "body_review_required"], | ||
}, | ||
), | ||
( | ||
_("Template review reminder"), | ||
{ | ||
"fields": ["subject_review_reminder", "body_review_reminder"], | ||
}, | ||
), | ||
( | ||
_("Template changes requested"), | ||
{ | ||
"fields": ["subject_changes_requested", "body_changes_requested"], | ||
}, | ||
), | ||
] |
76 changes: 76 additions & 0 deletions
76
backend/src/openarchiefbeheer/emails/migrations/0001_initial.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Generated by Django 4.2.11 on 2024-05-13 08:17 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
initial = True | ||
|
||
dependencies = [] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="EmailConfig", | ||
fields=[ | ||
( | ||
"id", | ||
models.AutoField( | ||
auto_created=True, | ||
primary_key=True, | ||
serialize=False, | ||
verbose_name="ID", | ||
), | ||
), | ||
( | ||
"subject_review_required", | ||
models.CharField( | ||
help_text="Subject of the email that will be sent to a reviewer when there is a destruction list ready to be reviewed.", | ||
max_length=250, | ||
verbose_name="subject review required", | ||
), | ||
), | ||
( | ||
"body_review_required", | ||
models.TextField( | ||
help_text="Body of the email that will be sent to a reviewer when there is a destruction list ready to be reviewed.", | ||
verbose_name="body review required", | ||
), | ||
), | ||
( | ||
"subject_review_reminder", | ||
models.CharField( | ||
help_text="Subject of the email that will be sent to a reviewer after a configured period of time if they still haven't reviewed a destruction list.", | ||
max_length=250, | ||
verbose_name="subject review reminder", | ||
), | ||
), | ||
( | ||
"body_review_reminder", | ||
models.TextField( | ||
help_text="Body of the email that will be sent to a reviewer after a configured period of time if they still haven't reviewed a destruction list.", | ||
verbose_name="body review reminder", | ||
), | ||
), | ||
( | ||
"subject_changes_requested", | ||
models.CharField( | ||
help_text="Subject of the email that will be sent to the record manager when a reviewer has requested changes to a destruction list.", | ||
max_length=250, | ||
verbose_name="subject changes requested", | ||
), | ||
), | ||
( | ||
"body_changes_requested", | ||
models.TextField( | ||
help_text="Body of the email that will be sent to the record manager when a reviewer has requested changes to a destruction list.", | ||
verbose_name="body changes requested", | ||
), | ||
), | ||
], | ||
options={ | ||
"verbose_name": "email configuration", | ||
"verbose_name_plural": "email configurations", | ||
}, | ||
), | ||
] |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from django.db import models | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from solo.models import SingletonModel | ||
|
||
|
||
class EmailConfig(SingletonModel): | ||
subject_review_required = models.CharField( | ||
max_length=250, | ||
verbose_name=_("subject review required"), | ||
help_text=_( | ||
"Subject of the email that will be sent to a reviewer " | ||
"when there is a destruction list ready to be reviewed." | ||
), | ||
) | ||
body_review_required = models.TextField( | ||
verbose_name=_("body review required"), | ||
help_text=_( | ||
"Body of the email that will be sent to a reviewer " | ||
"when there is a destruction list ready to be reviewed." | ||
), | ||
) | ||
subject_review_reminder = models.CharField( | ||
max_length=250, | ||
verbose_name=_("subject review reminder"), | ||
help_text=_( | ||
"Subject of the email that will be sent to a reviewer " | ||
"after a configured period of time if they still haven't reviewed a destruction list." | ||
), | ||
) | ||
body_review_reminder = models.TextField( | ||
verbose_name=_("body review reminder"), | ||
help_text=_( | ||
"Body of the email that will be sent to a reviewer " | ||
"after a configured period of time if they still haven't reviewed a destruction list." | ||
), | ||
) | ||
subject_changes_requested = models.CharField( | ||
max_length=250, | ||
verbose_name=_("subject changes requested"), | ||
help_text=_( | ||
"Subject of the email that will be sent to the record manager " | ||
"when a reviewer has requested changes to a destruction list." | ||
), | ||
) | ||
body_changes_requested = models.TextField( | ||
verbose_name=_("body changes requested"), | ||
help_text=_( | ||
"Body of the email that will be sent to the record manager " | ||
"when a reviewer has requested changes to a destruction list." | ||
), | ||
) | ||
|
||
class Meta: | ||
verbose_name = _("email configuration") | ||
verbose_name_plural = _("email configurations") | ||
|
||
def __str__(self): | ||
return "Email configuration" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from django.template.backends.django import DjangoTemplates | ||
|
||
|
||
class SandboxedTemplates(DjangoTemplates): | ||
def __init__(self, params: dict) -> None: | ||
params = params.copy() | ||
params.setdefault("NAME", "django_sandboxed") | ||
# no file system paths to look up files (also blocks {% include %} etc) | ||
params.setdefault("DIRS", []) | ||
params.setdefault("APP_DIRS", False) | ||
params.setdefault("OPTIONS", {}) | ||
|
||
super().__init__(params) | ||
|
||
def get_templatetag_libraries(self, custom_libraries: dict) -> dict: | ||
""" | ||
The parent returns template tag libraries from installed | ||
applications and the supplied custom_libraries argument. | ||
""" | ||
return {} | ||
|
||
def template_dirs(self) -> list: | ||
""" | ||
The parent returns a list of directories to search for templates. | ||
We only need to render from string. | ||
""" | ||
return [] | ||
|
||
|
||
def get_sandboxed_backend() -> SandboxedTemplates: | ||
return SandboxedTemplates({}) |
Empty file.
32 changes: 32 additions & 0 deletions
32
backend/src/openarchiefbeheer/emails/tests/test_rendering_emails.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from unittest.mock import patch | ||
|
||
from django.core import mail | ||
from django.test import TestCase | ||
|
||
from openarchiefbeheer.accounts.tests.factories import UserFactory | ||
from openarchiefbeheer.destruction.tests.factories import DestructionListFactory | ||
|
||
from ..models import EmailConfig | ||
from ..utils import send_review_request_email | ||
|
||
|
||
class RenderingEmailTemplatesTestCase(TestCase): | ||
|
||
def test_render_email_templates(self): | ||
user = UserFactory.create(username="reviewer1", email="[email protected]") | ||
destruction_list = DestructionListFactory.create(name="List 1") | ||
|
||
with patch( | ||
"openarchiefbeheer.emails.utils.EmailConfig.get_solo", | ||
return_value=EmailConfig( | ||
body_review_required="This is a test user: {{ user }} and a test list: {{ list }}." | ||
), | ||
): | ||
send_review_request_email(user, destruction_list) | ||
|
||
messages = mail.outbox | ||
|
||
self.assertEqual(len(messages), 1) | ||
self.assertEqual( | ||
messages[0].body, "This is a test user: reviewer1 and a test list: List 1." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from typing import TYPE_CHECKING | ||
|
||
from django.conf import settings | ||
from django.core.mail import send_mail | ||
|
||
if TYPE_CHECKING: | ||
from openarchiefbeheer.accounts.models import User | ||
from openarchiefbeheer.destruction.models import DestructionList | ||
|
||
from .models import EmailConfig | ||
from .render_backend import get_sandboxed_backend | ||
|
||
|
||
def send_review_request_email( | ||
user: "User", destruction_list: "DestructionList" | ||
) -> None: | ||
config = EmailConfig.get_solo() | ||
|
||
backend = get_sandboxed_backend() | ||
template = backend.from_string(config.body_review_required) | ||
|
||
formatted_body = template.render(context={"user": user, "list": destruction_list}) | ||
|
||
send_mail( | ||
subject=config.subject_review_required, | ||
message=formatted_body, | ||
from_email=settings.DEFAULT_FROM_EMAIL, | ||
recipient_list=[user.email], | ||
fail_silently=False, | ||
) |
14 changes: 14 additions & 0 deletions
14
backend/src/openarchiefbeheer/fixtures/default_emails.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[ | ||
{ | ||
"model": "emails.emailconfig", | ||
"pk": 1, | ||
"fields": { | ||
"subject_review_required": "Uw accordering van een vernietigingslijst wordt gevraagd", | ||
"body_review_required": "Beste {{ user }},\r\n\r\nUw accordering van een vernietigingslijst wordt gevraagd. U kunt in de Open-Archiefbeheer web app de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden.", | ||
"subject_review_reminder": "Uw accordering van een vernietigingslijst wordt gevraagd (herinnering)", | ||
"body_review_reminder": "Beste {{ user }}, \r\n\r\nU heeft kortgeleden een notificatie ontvangen over de Vernietigingslijst die wacht op uw goedkeuring. \r\n\r\nWij zien dat u nog niet geregeerd heeft, wilt u zo spoedig mogelijk op de Vernietigingslijst reageren.", | ||
"subject_changes_requested": "Voorstel voor wijziging van uw vernietigingslijst", | ||
"body_changes_requested": "Beste {{ user }},\r\n\r\nEr is een voorstel tot aanpassing van uw vernietigingslijst {{ list }}. U kunt de lijst en de voorgestelde wijziging in de Open-Archiefbeheer web app bekijken en af te handelen." | ||
} | ||
} | ||
] |