From d61847477907a52e58a0fc186b6570ad7289fe7b Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 15:32:14 +0100 Subject: [PATCH 1/7] :sparkles: [#638] Update user name in emails. --- backend/src/openarchiefbeheer/destruction/utils.py | 6 +++--- .../src/openarchiefbeheer/fixtures/default_emails.json | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/src/openarchiefbeheer/destruction/utils.py b/backend/src/openarchiefbeheer/destruction/utils.py index 614ba21d..77c89b98 100644 --- a/backend/src/openarchiefbeheer/destruction/utils.py +++ b/backend/src/openarchiefbeheer/destruction/utils.py @@ -63,7 +63,7 @@ def notify_reviewer( notify( subject=config.subject_review_required, body=config.body_review_required, - context={"user": user, "list_name": destruction_list.name}, + context={"user_name": user.get_full_name(), "list_name": destruction_list.name}, recipients=[user.email], ) @@ -80,7 +80,7 @@ def notify_author_positive_review( subject=config.subject_positive_review, body=config.body_positive_review, context={ - "user": user, + "user_name": user.get_full_name(), "list_name": destruction_list.name, "reviewer": last_reviewer, "current_reviewer": destruction_list.assignee, @@ -98,7 +98,7 @@ def notify_author_changes_requested( notify( subject=config.subject_changes_requested, body=config.body_changes_requested, - context={"user": user, "list_name": destruction_list.name}, + context={"user_name": user.get_full_name(), "list_name": destruction_list.name}, recipients=[user.email], ) diff --git a/backend/src/openarchiefbeheer/fixtures/default_emails.json b/backend/src/openarchiefbeheer/fixtures/default_emails.json index b11c9630..ae0fac7d 100644 --- a/backend/src/openarchiefbeheer/fixtures/default_emails.json +++ b/backend/src/openarchiefbeheer/fixtures/default_emails.json @@ -4,15 +4,15 @@ "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 hier {% destruction_list_link list_name 'review' %} de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden.", + "body_review_required": "Beste {{ user_name }},\r\n\r\nUw accordering van een vernietigingslijst wordt gevraagd. U kunt hier {% destruction_list_link list_name 'review' %} 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.", + "body_review_reminder": "Beste {{ user_name }}, \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_positive_review": "Goedkeuring vernietigingslijst", - "body_positive_review": "Beste {{ user }}, \r\n\r\nReviewer {{ reviewer }} heeft de Vernietigingslijst {{ list_name }} goedgekeurd. De lijst wacht nu op uw actie. U kunt hier de lijst bekijken: {% destruction_list_link list_name 'edit' %}", + "body_positive_review": "Beste {{ user_name }}, \r\n\r\nReviewer {{ reviewer }} heeft de Vernietigingslijst {{ list_name }} goedgekeurd. De lijst wacht nu op uw actie. U kunt hier de lijst bekijken: {% destruction_list_link list_name 'edit' %}", "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_name }}. U kunt de lijst en de voorgestelde wijziging hier {% destruction_list_link list_name 'process-review' %} bekijken en af te handelen.", + "body_changes_requested": "Beste {{ user_name }},\r\n\r\nEr is een voorstel tot aanpassing van uw vernietigingslijst {{ list_name }}. U kunt de lijst en de voorgestelde wijziging hier {% destruction_list_link list_name 'process-review' %} bekijken en af te handelen.", "subject_error_during_deletion": "Fout tijdens vernietiging", - "body_error_during_deletion": "Beste {{ user }},\r\n\r\nEr is een fout opgetreden tijdens het vernietigen van vernietigingslijst {{ list_name }}. Probeer het opnieuw of neem contact op met de IT afdeling.", + "body_error_during_deletion": "Beste {{ user_name }},\r\n\r\nEr is een fout opgetreden tijdens het vernietigen van vernietigingslijst {{ list_name }}. Probeer het opnieuw of neem contact op met de IT afdeling.", "subject_successful_deletion": "Lijst succesvol verwerkt", "body_successful_deletion": "Beste,\r\n\r\nLijst {{ list_name }} is succesvol verwerkt. Alle zaken en gerelateerde objecten zijn vernietigd." } From 8e84d97b0a1fa9a4dfe8b27548043e8bf90749f0 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 16:34:53 +0100 Subject: [PATCH 2/7] :sparkles: [#638] Add HTML email --- .../openarchiefbeheer/destruction/signals.py | 6 +- .../openarchiefbeheer/destruction/utils.py | 35 ++-- ...lconfig_body_changes_requested_and_more.py | 197 ++++++++++++++++++ .../src/openarchiefbeheer/emails/models.py | 104 +++++++-- 4 files changed, 306 insertions(+), 36 deletions(-) create mode 100644 backend/src/openarchiefbeheer/emails/migrations/0007_remove_emailconfig_body_changes_requested_and_more.py diff --git a/backend/src/openarchiefbeheer/destruction/signals.py b/backend/src/openarchiefbeheer/destruction/signals.py index d9dd6490..7881e6cb 100644 --- a/backend/src/openarchiefbeheer/destruction/signals.py +++ b/backend/src/openarchiefbeheer/destruction/signals.py @@ -47,7 +47,8 @@ def notify_author_of_failure(sender: DestructionList, **kwargs): notify( subject=config.subject_error_during_deletion, - body=config.body_error_during_deletion, + body_html=config.body_error_during_deletion_html, + body_text=config.body_error_during_deletion_text, context={"list_name": sender.name}, recipients=[sender.author.email], ) @@ -62,7 +63,8 @@ def notify_co_reviewers(sender: DestructionList, **kwargs): config = EmailConfig.get_solo() notify( subject=config.subject_co_review_request, - body=config.body_co_review_request, + body_html=config.body_co_review_request_html, + body_text=config.body_co_review_request_text, context={"list_name": sender.name}, recipients=[co_reviewer["user"].email for co_reviewer in added_co_reviewers], ) diff --git a/backend/src/openarchiefbeheer/destruction/utils.py b/backend/src/openarchiefbeheer/destruction/utils.py index 77c89b98..6f18023e 100644 --- a/backend/src/openarchiefbeheer/destruction/utils.py +++ b/backend/src/openarchiefbeheer/destruction/utils.py @@ -2,7 +2,7 @@ from typing import Protocol from django.conf import settings -from django.core.mail import send_mail +from django.core.mail import EmailMultiAlternatives from django.db import transaction from django.db.models import OuterRef, Q, QuerySet, Subquery from django.utils import timezone @@ -36,22 +36,27 @@ ) -def notify(subject: str, body: str, context: dict, recipients: list[str]) -> None: - if body == "" or subject == "" or len(recipients) == 0: +def notify( + subject: str, body_html: str, body_text: str, context: dict, recipients: list[str] +) -> None: + if body_text == "" or body_html == "" or subject == "" or len(recipients) == 0: return backend = get_sandboxed_backend() - template = backend.from_string(body) - formatted_body = template.render(context=context) + template_html = backend.from_string(body_html) + template_text = backend.from_string(body_text) + html_content = template_html.render(context=context) + text_content = template_text.render(context=context) - send_mail( + message = EmailMultiAlternatives( subject=subject, - message=formatted_body, + body=text_content, from_email=settings.DEFAULT_FROM_EMAIL, - recipient_list=recipients, - fail_silently=False, + to=recipients, ) + message.attach_alternative(html_content, "text/html") + message.send() def notify_reviewer( @@ -62,7 +67,8 @@ def notify_reviewer( notify( subject=config.subject_review_required, - body=config.body_review_required, + body_text=config.body_review_required_text, + body_html=config.body_review_required_html, context={"user_name": user.get_full_name(), "list_name": destruction_list.name}, recipients=[user.email], ) @@ -78,7 +84,8 @@ def notify_author_positive_review( notify( subject=config.subject_positive_review, - body=config.body_positive_review, + body_text=config.body_positive_review_text, + body_html=config.body_positive_review_html, context={ "user_name": user.get_full_name(), "list_name": destruction_list.name, @@ -97,7 +104,8 @@ def notify_author_changes_requested( notify( subject=config.subject_changes_requested, - body=config.body_changes_requested, + body_text=config.body_changes_requested_text, + body_html=config.body_changes_requested_html, context={"user_name": user.get_full_name(), "list_name": destruction_list.name}, recipients=[user.email], ) @@ -109,7 +117,8 @@ def notify_assignees_successful_deletion(destruction_list: DestructionList) -> N notify( subject=config.subject_successful_deletion, - body=config.body_successful_deletion, + body_text=config.body_successful_deletion_text, + body_html=config.body_successful_deletion_html, context={ "list_name": destruction_list.name, }, diff --git a/backend/src/openarchiefbeheer/emails/migrations/0007_remove_emailconfig_body_changes_requested_and_more.py b/backend/src/openarchiefbeheer/emails/migrations/0007_remove_emailconfig_body_changes_requested_and_more.py new file mode 100644 index 00000000..edb1227b --- /dev/null +++ b/backend/src/openarchiefbeheer/emails/migrations/0007_remove_emailconfig_body_changes_requested_and_more.py @@ -0,0 +1,197 @@ +# Generated by Django 4.2.17 on 2025-01-23 15:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("emails", "0006_emailconfig_body_co_review_request_and_more"), + ] + + operations = [ + migrations.RemoveField( + model_name="emailconfig", + name="body_changes_requested", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_co_review_request", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_error_during_deletion", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_positive_review", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_review_reminder", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_review_required", + ), + migrations.RemoveField( + model_name="emailconfig", + name="body_successful_deletion", + ), + migrations.AddField( + model_name="emailconfig", + name="body_changes_requested_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to the record manager when a reviewer has requested changes to a destruction list.", + verbose_name="html body changes requested", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_changes_requested_text", + field=models.TextField( + blank=True, + help_text="Plain 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="text body changes requested", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_co_review_request_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to the co-reviewer(s) when the main reviewer assigns them.", + verbose_name="HTML body co-review request", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_co_review_request_text", + field=models.TextField( + blank=True, + help_text="Plain text body of the email that will be sent to the co-reviewer(s) when the main reviewer assigns them.", + verbose_name="text body co-review request", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_error_during_deletion_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to the record manager when an error happened during deletion.", + verbose_name="HTML body error during deletion", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_error_during_deletion_text", + field=models.TextField( + blank=True, + help_text="Plain text body of the email that will be sent to the record manager when an error happened during deletion.", + verbose_name="text body error during deletion", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_positive_review_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to the record manager when a reviewer has approved a destruction list.", + verbose_name="html body positive review", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_positive_review_text", + field=models.TextField( + blank=True, + help_text="Plain text body of the email that will be sent to the record manager when a reviewer has approved a destruction list.", + verbose_name="text body positive review", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_review_reminder_html", + field=models.TextField( + blank=True, + help_text="HTML 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="html body review reminder", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_review_reminder_text", + field=models.TextField( + blank=True, + help_text="Plain 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="text body review reminder", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_review_required_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to a reviewer when there is a destruction list ready to be reviewed.", + verbose_name="html body review required", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_review_required_text", + field=models.TextField( + blank=True, + help_text="Plain text body of the email that will be sent to a reviewer when there is a destruction list ready to be reviewed.", + verbose_name="text body review required", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_successful_deletion_html", + field=models.TextField( + blank=True, + help_text="HTML body of the email that will be sent to all the assignees when a list is successfully deleted.", + verbose_name="HTML body successful deletion", + ), + ), + migrations.AddField( + model_name="emailconfig", + name="body_successful_deletion_text", + field=models.TextField( + blank=True, + help_text="Text body of the email that will be sent to all the assignees when a list is successfully deleted.", + verbose_name="text body successful deletion", + ), + ), + migrations.AlterField( + model_name="emailconfig", + name="subject_changes_requested", + field=models.CharField( + blank=True, + 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", + ), + ), + migrations.AlterField( + model_name="emailconfig", + name="subject_review_reminder", + field=models.CharField( + blank=True, + 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", + ), + ), + migrations.AlterField( + model_name="emailconfig", + name="subject_review_required", + field=models.CharField( + blank=True, + 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", + ), + ), + ] diff --git a/backend/src/openarchiefbeheer/emails/models.py b/backend/src/openarchiefbeheer/emails/models.py index 68394695..3a0cb90f 100644 --- a/backend/src/openarchiefbeheer/emails/models.py +++ b/backend/src/openarchiefbeheer/emails/models.py @@ -12,13 +12,23 @@ class EmailConfig(SingletonModel): "Subject of the email that will be sent to a reviewer " "when there is a destruction list ready to be reviewed." ), + blank=True, ) - body_review_required = models.TextField( - verbose_name=_("body review required"), + body_review_required_html = models.TextField( + verbose_name=_("html body review required"), help_text=_( - "Body of the email that will be sent to a reviewer " + "HTML body of the email that will be sent to a reviewer " "when there is a destruction list ready to be reviewed." ), + blank=True, + ) + body_review_required_text = models.TextField( + verbose_name=_("text body review required"), + help_text=_( + "Plain text body of the email that will be sent to a reviewer " + "when there is a destruction list ready to be reviewed." + ), + blank=True, ) subject_review_reminder = models.CharField( max_length=250, @@ -27,13 +37,23 @@ class EmailConfig(SingletonModel): "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." ), + blank=True, ) - body_review_reminder = models.TextField( - verbose_name=_("body review reminder"), + body_review_reminder_html = models.TextField( + verbose_name=_("html body review reminder"), help_text=_( - "Body of the email that will be sent to a reviewer " + "HTML 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." ), + blank=True, + ) + body_review_reminder_text = models.TextField( + verbose_name=_("text body review reminder"), + help_text=_( + "Plain 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." + ), + blank=True, ) subject_changes_requested = models.CharField( max_length=250, @@ -42,13 +62,23 @@ class EmailConfig(SingletonModel): "Subject of the email that will be sent to the record manager " "when a reviewer has requested changes to a destruction list." ), + blank=True, + ) + body_changes_requested_html = models.TextField( + verbose_name=_("html body changes requested"), + help_text=_( + "HTML body of the email that will be sent to the record manager " + "when a reviewer has requested changes to a destruction list." + ), + blank=True, ) - body_changes_requested = models.TextField( - verbose_name=_("body changes requested"), + body_changes_requested_text = models.TextField( + verbose_name=_("text body changes requested"), help_text=_( - "Body of the email that will be sent to the record manager " + "Plain text body of the email that will be sent to the record manager " "when a reviewer has requested changes to a destruction list." ), + blank=True, ) subject_positive_review = models.CharField( max_length=250, @@ -59,10 +89,18 @@ class EmailConfig(SingletonModel): ), blank=True, ) - body_positive_review = models.TextField( - verbose_name=_("body positive review"), + body_positive_review_html = models.TextField( + verbose_name=_("html body positive review"), help_text=_( - "Body of the email that will be sent to the record manager " + "HTML body of the email that will be sent to the record manager " + "when a reviewer has approved a destruction list." + ), + blank=True, + ) + body_positive_review_text = models.TextField( + verbose_name=_("text body positive review"), + help_text=_( + "Plain text body of the email that will be sent to the record manager " "when a reviewer has approved a destruction list." ), blank=True, @@ -76,10 +114,18 @@ class EmailConfig(SingletonModel): ), blank=True, ) - body_co_review_request = models.TextField( - verbose_name=_("body co-review request"), + body_co_review_request_html = models.TextField( + verbose_name=_("HTML body co-review request"), + help_text=_( + "HTML body of the email that will be sent to the co-reviewer(s) " + "when the main reviewer assigns them." + ), + blank=True, + ) + body_co_review_request_text = models.TextField( + verbose_name=_("text body co-review request"), help_text=_( - "Body of the email that will be sent to the co-reviewer(s) " + "Plain text body of the email that will be sent to the co-reviewer(s) " "when the main reviewer assigns them." ), blank=True, @@ -93,10 +139,18 @@ class EmailConfig(SingletonModel): ), blank=True, ) - body_error_during_deletion = models.TextField( - verbose_name=_("body error during deletion"), + body_error_during_deletion_html = models.TextField( + verbose_name=_("HTML body error during deletion"), help_text=_( - "Body of the email that will be sent to the record manager " + "HTML body of the email that will be sent to the record manager " + "when an error happened during deletion." + ), + blank=True, + ) + body_error_during_deletion_text = models.TextField( + verbose_name=_("text body error during deletion"), + help_text=_( + "Plain text body of the email that will be sent to the record manager " "when an error happened during deletion." ), blank=True, @@ -110,10 +164,18 @@ class EmailConfig(SingletonModel): ), blank=True, ) - body_successful_deletion = models.TextField( - verbose_name=_("body successful deletion"), + body_successful_deletion_html = models.TextField( + verbose_name=_("HTML body successful deletion"), + help_text=_( + "HTML body of the email that will be sent to all the assignees " + "when a list is successfully deleted." + ), + blank=True, + ) + body_successful_deletion_text = models.TextField( + verbose_name=_("text body successful deletion"), help_text=_( - "Body of the email that will be sent to all the assignees " + "Text body of the email that will be sent to all the assignees " "when a list is successfully deleted." ), blank=True, From 55247575b417493fa86fa10623ef5ead61bb921b Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 16:35:17 +0100 Subject: [PATCH 3/7] :sparkles: [#638] Update admin --- backend/src/openarchiefbeheer/emails/admin.py | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/backend/src/openarchiefbeheer/emails/admin.py b/backend/src/openarchiefbeheer/emails/admin.py index 75564aee..607a1f12 100644 --- a/backend/src/openarchiefbeheer/emails/admin.py +++ b/backend/src/openarchiefbeheer/emails/admin.py @@ -14,22 +14,32 @@ class EmailConfigAdmin(SingletonModelAdmin): { "fields": [ "subject_review_required", - "body_review_required", + "body_review_required_html", + "body_review_required_text", "subject_co_review_request", - "body_co_review_request", + "body_co_review_request_html", + "body_co_review_request_text", ], }, ), ( _("Template review reminder"), { - "fields": ["subject_review_reminder", "body_review_reminder"], + "fields": [ + "subject_review_reminder", + "body_review_reminder_html", + "body_review_reminder_text", + ], }, ), ( _("Template changes requested"), { - "fields": ["subject_changes_requested", "body_changes_requested"], + "fields": [ + "subject_changes_requested", + "body_changes_requested_html", + "body_changes_requested_text", + ], }, ), ( @@ -37,7 +47,8 @@ class EmailConfigAdmin(SingletonModelAdmin): { "fields": [ "subject_positive_review", - "body_positive_review", + "body_positive_review_html", + "body_positive_review_text", ] }, ), @@ -46,7 +57,8 @@ class EmailConfigAdmin(SingletonModelAdmin): { "fields": [ "subject_error_during_deletion", - "body_error_during_deletion", + "body_error_during_deletion_html", + "body_error_during_deletion_text", ] }, ), @@ -55,7 +67,8 @@ class EmailConfigAdmin(SingletonModelAdmin): { "fields": [ "subject_successful_deletion", - "body_successful_deletion", + "body_successful_deletion_html", + "body_successful_deletion_text", ] }, ), From 894c463571a9fff2c49544cececfab348ef4e760 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 16:35:47 +0100 Subject: [PATCH 4/7] :bento: [#638] Update email fixture --- .../fixtures/default_emails.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/backend/src/openarchiefbeheer/fixtures/default_emails.json b/backend/src/openarchiefbeheer/fixtures/default_emails.json index ae0fac7d..b6f103ce 100644 --- a/backend/src/openarchiefbeheer/fixtures/default_emails.json +++ b/backend/src/openarchiefbeheer/fixtures/default_emails.json @@ -4,17 +4,23 @@ "pk": 1, "fields": { "subject_review_required": "Uw accordering van een vernietigingslijst wordt gevraagd", - "body_review_required": "Beste {{ user_name }},\r\n\r\nUw accordering van een vernietigingslijst wordt gevraagd. U kunt hier {% destruction_list_link list_name 'review' %} de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden.", + "body_review_required_html": "Beste {{ user_name }},\r\n\r\nUw accordering van een vernietigingslijst wordt gevraagd. U kunt hier de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden.", + "body_review_required_text": "Beste {{ user_name }},\r\n\r\nUw accordering van een vernietigingslijst wordt gevraagd. U kunt hier {% destruction_list_link list_name 'review' %} 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_name }}, \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.", + "body_review_reminder_html": "Beste {{ user_name }}, \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.", + "body_review_reminder_text": "Beste {{ user_name }}, \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_positive_review": "Goedkeuring vernietigingslijst", - "body_positive_review": "Beste {{ user_name }}, \r\n\r\nReviewer {{ reviewer }} heeft de Vernietigingslijst {{ list_name }} goedgekeurd. De lijst wacht nu op uw actie. U kunt hier de lijst bekijken: {% destruction_list_link list_name 'edit' %}", + "body_positive_review_html": "Beste {{ user_name }}, \r\n\r\nReviewer {{ reviewer }} heeft de Vernietigingslijst {{ list_name }} goedgekeurd. De lijst wacht nu op uw actie. U kunt hier de lijst bekijken.", + "body_positive_review_text": "Beste {{ user_name }}, \r\n\r\nReviewer {{ reviewer }} heeft de Vernietigingslijst {{ list_name }} goedgekeurd. De lijst wacht nu op uw actie. U kunt hier de lijst bekijken.", "subject_changes_requested": "Voorstel voor wijziging van uw vernietigingslijst", - "body_changes_requested": "Beste {{ user_name }},\r\n\r\nEr is een voorstel tot aanpassing van uw vernietigingslijst {{ list_name }}. U kunt de lijst en de voorgestelde wijziging hier {% destruction_list_link list_name 'process-review' %} bekijken en af te handelen.", + "body_changes_requested_html": "Beste {{ user_name }},\r\n\r\nEr is een voorstel tot aanpassing van uw vernietigingslijst {{ list_name }}. U kunt de lijst en de voorgestelde wijziging hier bekijken en af te handelen.", + "body_changes_requested_text": "Beste {{ user_name }},\r\n\r\nEr is een voorstel tot aanpassing van uw vernietigingslijst {{ list_name }}. U kunt de lijst en de voorgestelde wijziging hier {% destruction_list_link list_name 'process-review' %} bekijken en af te handelen.", "subject_error_during_deletion": "Fout tijdens vernietiging", - "body_error_during_deletion": "Beste {{ user_name }},\r\n\r\nEr is een fout opgetreden tijdens het vernietigen van vernietigingslijst {{ list_name }}. Probeer het opnieuw of neem contact op met de IT afdeling.", + "body_error_during_deletion_html": "Beste {{ user_name }},\r\n\r\nEr is een fout opgetreden tijdens het vernietigen van vernietigingslijst {{ list_name }}. Probeer het opnieuw of neem contact op met de IT afdeling.", + "body_error_during_deletion_text": "Beste {{ user_name }},\r\n\r\nEr is een fout opgetreden tijdens het vernietigen van vernietigingslijst {{ list_name }}. Probeer het opnieuw of neem contact op met de IT afdeling.", "subject_successful_deletion": "Lijst succesvol verwerkt", - "body_successful_deletion": "Beste,\r\n\r\nLijst {{ list_name }} is succesvol verwerkt. Alle zaken en gerelateerde objecten zijn vernietigd." + "body_successful_deletion_html": "Beste,\r\n\r\nLijst {{ list_name }} is succesvol verwerkt. Alle zaken en gerelateerde objecten zijn vernietigd.", + "body_successful_deletion_text": "Beste,\r\n\r\nLijst {{ list_name }} is succesvol verwerkt. Alle zaken en gerelateerde objecten zijn vernietigd." } } ] \ No newline at end of file From 643e16e759ab360a12c93886481b5096fd0932dc Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 16:36:10 +0100 Subject: [PATCH 5/7] :white_check_mark: [#638] Update tests --- .../destruction/tests/endpoints/test_co_reviewers.py | 6 ++++-- .../destruction/tests/test_endpoints.py | 3 ++- .../destruction/tests/test_serializers.py | 3 ++- .../openarchiefbeheer/destruction/tests/test_signals.py | 6 ++++-- .../openarchiefbeheer/destruction/tests/test_tasks.py | 9 ++++++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/src/openarchiefbeheer/destruction/tests/endpoints/test_co_reviewers.py b/backend/src/openarchiefbeheer/destruction/tests/endpoints/test_co_reviewers.py index 7c66ac33..6ee5b36d 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/endpoints/test_co_reviewers.py +++ b/backend/src/openarchiefbeheer/destruction/tests/endpoints/test_co_reviewers.py @@ -93,7 +93,8 @@ def test_fully_update_co_reviewers(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_co_review_request="Please co-review!", - body_co_review_request="You have been invited to co-review.", + body_co_review_request_text="You have been invited to co-review.", + body_co_review_request_html="You have been invited to co-review.", ), ), ): @@ -208,7 +209,8 @@ def test_partially_update_co_reviewers(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_co_review_request="Please co-review!", - body_co_review_request="You have been invited to co-review.", + body_co_review_request_text="You have been invited to co-review.", + body_co_review_request_html="You have been invited to co-review.", ), ), ): diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py index a31fe08c..f3415f7f 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py @@ -737,7 +737,8 @@ def test_mark_as_ready_to_review(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_review_required="Destruction list review request", - body_review_required="Please review the list", + body_review_required_text="Please review the list", + body_review_required_html="Please review the list", ), ), ): diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_serializers.py b/backend/src/openarchiefbeheer/destruction/tests/test_serializers.py index 375157fe..2c193c61 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_serializers.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_serializers.py @@ -922,7 +922,8 @@ def test_create_review_accepted(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_positive_review="Review accepted", - body_positive_review="Yuppiii reviewer accepted!", + body_positive_review_text="Yuppiii reviewer accepted!", + body_positive_review_html="Yuppiii reviewer accepted!", ), ), ): diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_signals.py b/backend/src/openarchiefbeheer/destruction/tests/test_signals.py index 6dd5b38d..e87fb700 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_signals.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_signals.py @@ -19,7 +19,8 @@ class SignalsTests(TestCase): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_changes_requested="Changes requested", - body_changes_requested="Changes requested", + body_changes_requested_text="Changes requested", + body_changes_requested_html="Changes requested", ), ) def test_no_email_sent_if_not_review_created(self, m): @@ -52,7 +53,8 @@ def test_failure_during_deletion_sends_signal(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_error_during_deletion="FAILURE!!", - body_error_during_deletion="ERROR AAAh!", + body_error_during_deletion_text="ERROR AAAh!", + body_error_during_deletion_html="ERROR AAAh!", ), ), ): diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_tasks.py b/backend/src/openarchiefbeheer/destruction/tests/test_tasks.py index 6d2f16dc..1762b8d0 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_tasks.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_tasks.py @@ -131,7 +131,8 @@ def test_changes_to_both_zaak_and_destruction_list_item(self, m): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_review_required="Destruction list review request", - body_review_required="Please review the list", + body_review_required_text="Please review the list", + body_review_required_html="Please review the list", ), ), ): @@ -188,7 +189,8 @@ def test_reject_suggestion_does_not_change_zaak(self, m): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_review_required="Destruction list review request", - body_review_required="Please review the list", + body_review_required_text="Please review the list", + body_review_required_html="Please review the list", ), ), ): @@ -615,7 +617,8 @@ def test_complete_and_notify(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_successful_deletion="DELETED!", - body_successful_deletion="Wohoo deleted list", + body_successful_deletion_text="Wohoo deleted list", + body_successful_deletion_html="Wohoo deleted list", ), ), patch("openarchiefbeheer.destruction.utils.create_zaak_for_report"), From 6837a50e8d4000fbf524fd88e7f07468f731d759 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Thu, 23 Jan 2025 16:49:36 +0100 Subject: [PATCH 6/7] :white_check_mark: [#638] Add test for alternative body format --- .../destruction/tests/test_endpoints.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py index f3415f7f..3064640f 100644 --- a/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py +++ b/backend/src/openarchiefbeheer/destruction/tests/test_endpoints.py @@ -2,6 +2,7 @@ from django.contrib.auth.models import Group from django.core import mail +from django.test import override_settings from django.utils.translation import gettext_lazy as _ from furl import furl @@ -706,6 +707,7 @@ def test_cannot_mark_as_final_if_posted_user_is_not_archivist(self): _("The chosen user does not have the permission to review a final list."), ) + @override_settings(FRONTEND_URL="https://openarchiefbeheer.nl/") def test_mark_as_ready_to_review(self): record_manager = UserFactory.create( username="dolly123", @@ -737,8 +739,8 @@ def test_mark_as_ready_to_review(self): "openarchiefbeheer.destruction.utils.EmailConfig.get_solo", return_value=EmailConfig( subject_review_required="Destruction list review request", - body_review_required_text="Please review the list", - body_review_required_html="Please review the list", + body_review_required_text="Please review the list here: {% destruction_list_link list_name 'review' %}", + body_review_required_html="Please review the list here.", ), ), ): @@ -760,6 +762,15 @@ def test_mark_as_ready_to_review(self): self.assertEqual(len(sent_mail), 1) self.assertEqual(sent_mail[0].subject, "Destruction list review request") self.assertEqual(sent_mail[0].recipients(), [reviewer.user.email]) + self.assertEqual( + sent_mail[0].body, + f"Please review the list here: https://openarchiefbeheer.nl/destruction-lists/{destruction_list.uuid}/review", + ) + self.assertEqual( + sent_mail[0].alternatives[0][0], + f'Please review the list here.', + ) + self.assertEqual(sent_mail[0].alternatives[0][1], "text/html") logs = TimelineLog.objects.for_object(destruction_list) From 726fe907ea6ed4489b750f87ba6588de44b6051b Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Fri, 24 Jan 2025 10:34:45 +0100 Subject: [PATCH 7/7] :memo: [#638] Update docs --- .../3-administrator/3.1-email-templates.rst | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/docs/manual/3-administrator/3.1-email-templates.rst b/backend/docs/manual/3-administrator/3.1-email-templates.rst index 1ce49242..47dcb7b4 100644 --- a/backend/docs/manual/3-administrator/3.1-email-templates.rst +++ b/backend/docs/manual/3-administrator/3.1-email-templates.rst @@ -20,6 +20,27 @@ Hier kun je de onderwerpen en de emailteksten voor de emails die worden gestuurd - De record manager als een reviewer aanpassingen heeft aangevraagd op een lijst. - De record manager en de reviewers als een lijst succesvol is vernietigd. +Tekst en HTML sjablonen moeten geconfigureerd worden voor elke email. Een voorbeeld voor de email +die wordt gestuurd naar een beoordelaar als een lijst goedgekeurd moet worden zou kunnen is: + +- Tekst: + +.. code:: + + Beste {{ user_name }}, + + Uw accordering van een vernietigingslijst wordt gevraagd. + U kunt hier {% destruction_list_link list_name 'review' %} de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden. + +- HTML: + +.. code:: + + Beste {{ user_name }}, + + Uw accordering van een vernietigingslijst wordt gevraagd. + U kunt hier de lijst bekijken om te controleren of de zaken op de lijst daadwerkelijk vernietigd kunnen worden. + Beschikbare Sjabloonvariabelen ------------------------------ @@ -40,5 +61,5 @@ Voor elke emailtekst sjabloon, deze variabelen zijn beschikbaar: :widths: 100, 70 "``{{ list_name }}``", "Geeft de naam van de vernietigingslijst." - "``{{ user }}``", "Geeft de voornaam, de achternaam en de gebruikersnaam (tussen haakjes) van de persoon die de email ontvangt." + "``{{ user_name }}``", "Geeft de voornaam en de achternaam van de persoon die de email ontvangt." "``{{ reviewer }}``", "Geeft de voornaam, de achternaam en de gebruikersnaam (tussen haakjes) van de reviewer van de vernietigingslijst. Deze variabele is alleen beschikbaar in de sjabloon voor de email naar de record manager na een goedkeuring van de reviewer."