Skip to content

Commit

Permalink
feat(Emails): avoir les logs d'envois des TemplateTransactional (#1337)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn authored Jul 18, 2024
1 parent 6d48f7f commit 3addac3
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 66 deletions.
21 changes: 20 additions & 1 deletion lemarche/conversations/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib import admin
from django.http import HttpResponseRedirect

from lemarche.conversations.models import Conversation, TemplateTransactional
from lemarche.conversations.models import Conversation, TemplateTransactional, TemplateTransactionalSendLog
from lemarche.utils.admin.admin_site import admin_site
from lemarche.utils.fields import pretty_print_readonly_jsonfield_to_table
from lemarche.www.conversations.tasks import send_first_email_from_conversation
Expand Down Expand Up @@ -144,3 +144,22 @@ class TemplateTransactionalAdmin(admin.ModelAdmin):
("Paramètres d'envoi", {"fields": ("mailjet_id", "brevo_id", "source", "is_active")}),
("Dates", {"fields": ("created_at", "updated_at")}),
)


@admin.register(TemplateTransactionalSendLog, site=admin_site)
class TemplateTransactionalSendLogAdmin(admin.ModelAdmin):
list_display = ["id", "template_transactional", "content_type", "created_at"]
list_filter = [("content_type", admin.RelatedOnlyFieldListFilter)]
search_fields = ["id", "template_transactional"]
search_help_text = "Cherche sur les champs : ID, Template transactionnel"

readonly_fields = [field.name for field in TemplateTransactionalSendLog._meta.fields]

def has_add_permission(self, request):
return False

def has_change_permission(self, request, obj=None):
return False

def has_delete_permission(self, request, obj=None):
return False
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Generated by Django 4.2.13 on 2024-07-15 10:43

import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("conversations", "0015_remove_templatetransactional_email_from_email_and_more"),
]

operations = [
migrations.CreateModel(
name="TemplateTransactionalSendLog",
fields=[
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
("object_id", models.PositiveBigIntegerField(blank=True, null=True)),
("extra_data", models.JSONField(default=dict, editable=False, verbose_name="Données complémentaires")),
(
"created_at",
models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"),
),
("updated_at", models.DateTimeField(auto_now=True, verbose_name="Date de modification")),
(
"content_type",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="contenttypes.contenttype",
),
),
(
"template_transactional",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="send_logs",
to="conversations.templatetransactional",
verbose_name="Template transactionnel",
),
),
],
options={
"verbose_name": "Template transactionnel: logs d'envois",
"verbose_name_plural": "Templates transactionnels: logs d'envois",
},
),
]
59 changes: 41 additions & 18 deletions lemarche/conversations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from uuid import uuid4

from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import IntegrityError, models
from django.db.models import Func, IntegerField, Q
from django.utils import timezone
Expand Down Expand Up @@ -254,6 +256,9 @@ def get_template_id(self):
return self.brevo_id
return None

def create_send_log(self, **kwargs):
TemplateTransactionalSendLog.objects.create(template_transactional=self, **kwargs)

def send_transactional_email(
self,
recipient_email,
Expand All @@ -264,23 +269,41 @@ def send_transactional_email(
from_name=settings.DEFAULT_FROM_NAME,
):
if self.is_active:
args = {
"template_id": self.get_template_id,
"recipient_email": recipient_email,
"recipient_name": recipient_name,
"variables": variables,
"subject": subject,
"from_email": from_email,
"from_name": from_name,
}
if self.source == conversation_constants.SOURCE_MAILJET:
api_mailjet.send_transactional_email_with_template(
template_id=self.get_template_id,
recipient_email=recipient_email,
recipient_name=recipient_name,
variables=variables,
subject=subject,
from_email=from_email,
from_name=from_name,
)
result = api_mailjet.send_transactional_email_with_template(**args)
elif self.source == conversation_constants.SOURCE_BREVO:
api_brevo.send_transactional_email_with_template(
template_id=self.get_template_id,
recipient_email=recipient_email,
recipient_name=recipient_name,
variables=variables,
subject=subject,
from_email=from_email,
from_name=from_name,
)
result = api_brevo.send_transactional_email_with_template(**args)
# create log
self.create_send_log(extra_data={"source": self.source, "variables": args, "response": result()})


class TemplateTransactionalSendLog(models.Model):
template_transactional = models.ForeignKey(
"conversations.TemplateTransactional",
verbose_name="Template transactionnel",
on_delete=models.SET_NULL,
null=True,
related_name="send_logs",
)

content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE)
object_id = models.PositiveBigIntegerField(blank=True, null=True)
content_object = GenericForeignKey("content_type", "object_id")

extra_data = models.JSONField(verbose_name="Données complémentaires", editable=False, default=dict)

created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now)
updated_at = models.DateTimeField(verbose_name="Date de modification", auto_now=True)

class Meta:
verbose_name = "Template transactionnel: logs d'envois"
verbose_name_plural = "Templates transactionnels: logs d'envois"
1 change: 1 addition & 0 deletions lemarche/siaes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,7 @@ class Siae(models.Model):
"Nombre de besoins intéressés", help_text=RECALCULATED_FIELD_HELP_TEXT, default=0
)
logs = models.JSONField(verbose_name="Logs historiques", editable=False, default=list)
transactional_send_logs = GenericRelation("conversations.TemplateTransactionalSendLog", related_query_name="siae")
source = models.CharField(
max_length=20, choices=siae_constants.SOURCE_CHOICES, default=siae_constants.SOURCE_STAFF_C4_CREATED
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
La structure {{ siae_name|safe }} souhaite répondre en co-traitance
La structure {{ SIAE_NAME|safe }} souhaite répondre en co-traitance

Titre : {{ tender_title|safe }}
Type : {{ tender_kind|safe }}
Contact email de l'ESI: {{ siae_contact_email|safe }}
SIRET : {{ siae_siret|safe }}
Titre : {{ TENDER_TITLE|safe }}
Type : {{ TENDER_KIND|safe }}
Contact email de l'ESI: {{ SIAE_CONTACT_EMAIL|safe }}
SIRET : {{ SIAE_SIRET|safe }}

Lien dans l'admin : {{ tender_admin_url }}
Lien dans l'admin : {{ TENDER_ADMIN_URL }}
22 changes: 11 additions & 11 deletions lemarche/templates/tenders/create_notification_email_admin_body.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
Dépôt de besoin : ajout d'un nouveau {{ tender_kind|safe }}
Dépôt de besoin : ajout d'un nouveau {{ TENDER_KIND|safe }}

titre : {{ tender_title|safe }}
type : {{ tender_kind|safe }}
lieu d'intervention : {{ tender_location|safe }}
date de clôture des réponses : {{ tender_deadline_date|safe }}
contact : {{ tender_author_full_name|safe }}
entreprise : {{ tender_author_company|safe }}
si le Marché n'existait pas, auriez-vous consulté des prestataires inclusifs ? : {{ tender_scale_marche_useless|safe }}
status : {{ tender_status|safe }}
source: {{ tender_source|safe }}
titre : {{ TENDER_TITLE|safe }}
type : {{ TENDER_KIND|safe }}
lieu d'intervention : {{ TENDER_LOCATION|safe }}
date de clôture des réponses : {{ TENDER_DEADLINE_DATE|safe }}
contact : {{ TENDER_AUTHOR_FULL_NAME|safe }}
entreprise : {{ TENDER_AUTHOR_COMPANY|safe }}
si le Marché n'existait pas, auriez-vous consulté des prestataires inclusifs ? : {{ TENDER_SCALE_MARCHE_USELESS|safe }}
status : {{ TENDER_STATUS|safe }}
source: {{ TENDER_SOURCE|safe }}

Lien dans l'admin : {{ tender_admin_url }}
Lien dans l'admin : {{ TENDER_ADMIN_URL }}
1 change: 1 addition & 0 deletions lemarche/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ class User(AbstractUser):
"Date de dernière visite sur la page 'besoins'", blank=True, null=True
)
extra_data = models.JSONField(verbose_name="Données complémentaires", editable=False, default=dict)
transactional_send_logs = GenericRelation("conversations.TemplateTransactionalSendLog", related_query_name="user")

# is_active, is_staff, is_superuser

Expand Down
3 changes: 2 additions & 1 deletion lemarche/utils/apis/api_brevo.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ def send_transactional_email_with_template(
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(**data)
response = api_instance.send_transac_email(send_smtp_email)
logger.info("Brevo: send transactional email with template")
return response
# {'message_id': '<[email protected]>', 'message_ids': None}
return response.to_dict()
except ApiException as e:
print(f"Exception when calling SMTPApi->send_transac_email: {e}")
else:
Expand Down
1 change: 1 addition & 0 deletions lemarche/utils/apis/api_mailjet.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def send_transactional_email_with_template(
response = client.post(SEND_URL, json=data)
response.raise_for_status()
logger.info("Mailjet: send transactional email with template")
# {'Messages': [{'Status': 'success', 'CustomID': '', 'To': [{'Email': '<recipient_email>', 'MessageUUID': '<uuid>', 'MessageID': <id>, 'MessageHref': 'https://api.mailjet.com/v3/REST/message/<id>'}], 'Cc': [], 'Bcc': []}]} # noqa
return response.json()
except requests.exceptions.HTTPError as e:
logger.error("Error while fetching `%s`: %s", e.request.url, e)
Expand Down
18 changes: 18 additions & 0 deletions lemarche/www/dashboard_siaes/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ def send_siae_user_request_email_to_assignee(siae_user_request):
recipient_name = siae_user_request.assignee.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
"SIAE_USERS_URL": f"https://{get_domain_url()}{reverse_lazy('dashboard_siaes:siae_users', args=[siae_user_request.siae.slug])}", # noqa
}
Expand Down Expand Up @@ -57,8 +60,11 @@ def send_siae_user_request_response_email_to_initiator(siae_user_request):
recipient_name = siae_user_request.initiator.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
"DASHBOARD_URL": f"https://{get_domain_url()}{reverse_lazy('dashboard:home')}",
}
Expand Down Expand Up @@ -99,8 +105,11 @@ def send_siae_user_request_reminder_3_days_email_to_assignee(siae_user_request):
recipient_name = siae_user_request.assignee.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
"SIAE_USERS_URL": f"https://{get_domain_url()}{reverse_lazy('dashboard_siaes:siae_users', args=[siae_user_request.siae.slug])}", # noqa
}
Expand Down Expand Up @@ -131,8 +140,11 @@ def send_siae_user_request_reminder_3_days_email_to_initiator(siae_user_request)
recipient_name = siae_user_request.initiator.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
}

Expand Down Expand Up @@ -172,8 +184,11 @@ def send_siae_user_request_reminder_8_days_email_to_assignee(siae_user_request):
recipient_name = siae_user_request.assignee.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
"SIAE_USERS_URL": f"https://{get_domain_url()}{reverse_lazy('dashboard_siaes:siae_users', args=[siae_user_request.siae.slug])}", # noqa
}
Expand Down Expand Up @@ -204,8 +219,11 @@ def send_siae_user_request_reminder_8_days_email_to_initiator(siae_user_request)
recipient_name = siae_user_request.initiator.full_name

variables = {
"ASSIGNEE_ID": siae_user_request.assignee.id,
"ASSIGNEE_FULL_NAME": siae_user_request.assignee.full_name,
"INITIATIOR_ID": siae_user_request.initiator.id,
"INITIATOR_FULL_NAME": siae_user_request.initiator.full_name,
"SIAE_ID": siae_user_request.siae.id,
"SIAE_NAME": siae_user_request.siae.name_display,
"SUPPORT_URL": f"https://{get_domain_url()}{reverse_lazy('pages:contact')}?siret={siae_user_request.siae.siret}", # noqa
}
Expand Down
Loading

0 comments on commit 3addac3

Please sign in to comment.