diff --git a/lemarche/conversations/admin.py b/lemarche/conversations/admin.py index 786dd2c1d..1573cbaea 100644 --- a/lemarche/conversations/admin.py +++ b/lemarche/conversations/admin.py @@ -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 @@ -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 diff --git a/lemarche/conversations/migrations/0016_templatetransactionalsendlog.py b/lemarche/conversations/migrations/0016_templatetransactionalsendlog.py new file mode 100644 index 000000000..27db331ed --- /dev/null +++ b/lemarche/conversations/migrations/0016_templatetransactionalsendlog.py @@ -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", + }, + ), + ] diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index 4c1ab801a..844492247 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -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 @@ -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, @@ -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" diff --git a/lemarche/siaes/models.py b/lemarche/siaes/models.py index e3c159003..8929fd1ae 100644 --- a/lemarche/siaes/models.py +++ b/lemarche/siaes/models.py @@ -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 ) diff --git a/lemarche/templates/tenders/cocontracting_notification_email_admin_body.txt b/lemarche/templates/tenders/cocontracting_notification_email_admin_body.txt index 278c3b98f..14204dc89 100644 --- a/lemarche/templates/tenders/cocontracting_notification_email_admin_body.txt +++ b/lemarche/templates/tenders/cocontracting_notification_email_admin_body.txt @@ -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 }} diff --git a/lemarche/templates/tenders/create_notification_email_admin_body.txt b/lemarche/templates/tenders/create_notification_email_admin_body.txt index 890c35c00..c6205d599 100644 --- a/lemarche/templates/tenders/create_notification_email_admin_body.txt +++ b/lemarche/templates/tenders/create_notification_email_admin_body.txt @@ -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 }} diff --git a/lemarche/users/models.py b/lemarche/users/models.py index cc59c9b29..ed3e09097 100644 --- a/lemarche/users/models.py +++ b/lemarche/users/models.py @@ -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 diff --git a/lemarche/utils/apis/api_brevo.py b/lemarche/utils/apis/api_brevo.py index b220d3789..c05c634a6 100644 --- a/lemarche/utils/apis/api_brevo.py +++ b/lemarche/utils/apis/api_brevo.py @@ -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': '<202407151419.84958140835@smtp-relay.mailin.fr>', 'message_ids': None} + return response.to_dict() except ApiException as e: print(f"Exception when calling SMTPApi->send_transac_email: {e}") else: diff --git a/lemarche/utils/apis/api_mailjet.py b/lemarche/utils/apis/api_mailjet.py index 763239977..d1e95fd64 100644 --- a/lemarche/utils/apis/api_mailjet.py +++ b/lemarche/utils/apis/api_mailjet.py @@ -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': '', 'MessageUUID': '', 'MessageID': , 'MessageHref': 'https://api.mailjet.com/v3/REST/message/'}], 'Cc': [], 'Bcc': []}]} # noqa return response.json() except requests.exceptions.HTTPError as e: logger.error("Error while fetching `%s`: %s", e.request.url, e) diff --git a/lemarche/www/dashboard_siaes/tasks.py b/lemarche/www/dashboard_siaes/tasks.py index b5ccd51ca..87f02755d 100644 --- a/lemarche/www/dashboard_siaes/tasks.py +++ b/lemarche/www/dashboard_siaes/tasks.py @@ -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 } @@ -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')}", } @@ -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 } @@ -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, } @@ -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 } @@ -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 } diff --git a/lemarche/www/tenders/tasks.py b/lemarche/www/tenders/tasks.py index 4b43633ab..66e842e73 100644 --- a/lemarche/www/tenders/tasks.py +++ b/lemarche/www/tenders/tasks.py @@ -128,12 +128,15 @@ def send_tender_email_to_siae(tender: Tender, siae: Siae, email_subject: str, re tender_not_interested_url += f"&user_id={recipient_to_override.id}" variables = { + "SIAE_ID": siae.id, "SIAE_CONTACT_FIRST_NAME": siae.contact_first_name, "SIAE_SECTORS": siae.sectors_list_string(), "SIAE_PERIMETER": siae.geo_range_pretty_display, + "TENDER_ID": tender.id, "TENDER_TITLE": tender.title, "TENDER_AUTHOR_COMPANY": tender.author.company_name, "TENDER_KIND": tender.get_kind_display(), + "TENDER_KIND_LOWER": tender.get_kind_display().lower(), "TENDER_SECTORS": tender.sectors_list_string(), "TENDER_PERIMETERS": tender.location_display, "TENDER_AMOUNT": tender.amount_display, @@ -192,6 +195,7 @@ def send_tender_email_to_partner(email_subject: str, tender: Tender, partner: Pa recipient_list = whitelist_recipient_list(partner.contact_email_list) if recipient_list: variables = { + "TENDER_ID": tender.id, "TENDER_TITLE": tender.title, "TENDER_AUTHOR_COMPANY": tender.author.company_name, "TENDER_SECTORS": tender.sectors_list_string(), @@ -273,9 +277,11 @@ def send_tender_contacted_reminder_email_to_siae(tendersiae: TenderSiae, email_t recipient_name = tendersiae.siae.contact_email_name_display variables = { + "SIAE_ID": tendersiae.siae.id, "SIAE_CONTACT_FIRST_NAME": tendersiae.siae.contact_first_name, "SIAE_SECTORS": tendersiae.siae.sectors_list_string(), "SIAE_PERIMETER": tendersiae.siae.geo_range_pretty_display, + "TENDER_ID": tendersiae.tender.id, "TENDER_TITLE": tendersiae.tender.title, "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, "TENDER_KIND": tendersiae.tender.get_kind_display(), @@ -348,9 +354,11 @@ def send_tender_interested_reminder_email_to_siae( recipient_name = tendersiae.siae.contact_email_name_display variables = { + "SIAE_ID": tendersiae.siae.id, "SIAE_CONTACT_FIRST_NAME": tendersiae.siae.contact_first_name, "SIAE_SECTORS": tendersiae.siae.sectors_list_string(), "SIAE_PERIMETER": tendersiae.siae.geo_range_pretty_display, + "TENDER_ID": tendersiae.tender.id, "TENDER_TITLE": tendersiae.tender.title, "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, "TENDER_KIND": tendersiae.tender.get_kind_display(), @@ -394,7 +402,7 @@ def send_confirmation_published_email_to_author(tender: Tender): recipient_name = tender.author.full_name variables = { - "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, + "TENDER_ID": tender.id, "TENDER_TITLE": tender.title, "TENDER_KIND": tender.get_kind_display(), "TENDER_KIND_LOWER": tender.get_kind_display().lower(), @@ -402,6 +410,8 @@ def send_confirmation_published_email_to_author(tender: Tender): "TENDER_PERIMETERS": tender.location_display, "TENDER_AMOUNT": tender.amount_display, "TENDER_DEADLINE_DATE": date_to_string(tender.deadline_date), + "TENDER_AUTHOR_ID": tender.author.id, + "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, "TENDER_NB_MATCH": tender.siaes.count(), "TENDER_URL": get_object_share_url(tender), } @@ -465,8 +475,10 @@ def send_siae_interested_email_to_author(tender: Tender): recipient_name = tender.author.full_name variables = { - "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, + "TENDER_ID": tender.id, "TENDER_TITLE": tender.title, + "TENDER_AUTHOR_ID": tender.author.id, + "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, "TENDER_SIAE_INTERESTED_LIST_URL": f"{get_object_share_url(tender)}/prestataires", # noqa } @@ -492,18 +504,20 @@ def notify_admin_tender_created(tender: Tender): email_subject = f"Marché de l'inclusion : dépôt de besoin, ajout d'un nouveau {tender.get_kind_display()}" tender_admin_url = get_object_admin_url(tender) data_to_send = { - "tender_id": tender.id, - "tender_title": tender.title, - "tender_kind": tender.get_kind_display(), - "tender_location": tender.location_display, - "tender_deadline_date": tender.deadline_date, - "tender_author_full_name": tender.contact_full_name, - "tender_author_email": tender.author.email, - "tender_author_company": tender.author.company_name, - "tender_scale_marche_useless": tender.get_scale_marche_useless_display(), - "tender_status": tender.get_status_display(), - "tender_source": tender.get_source_display(), - "tender_admin_url": tender_admin_url, + "TENDER_ID": tender.id, + "TENDER_TITLE": tender.title, + "TENDER_KIND": tender.get_kind_display(), + "TENDER_KIND_LOWER": tender.get_kind_display().lower(), + "TENDER_LOCATION": tender.location_display, + "TENDER_DEADLINE_DATE": tender.deadline_date, + "TENDER_AUTHOR_ID": tender.author.id, + "TENDER_AUTHOR_FULL_NAME": tender.contact_full_name, + "TENDER_AUTHOR_EMAIL": tender.author.email, + "TENDER_AUTHOR_COMPANY": tender.author.company_name, + "TENDER_SCALE_MARCHE_USELESS": tender.get_scale_marche_useless_display(), + "TENDER_STATUS": tender.get_status_display(), + "TENDER_SOURCE": tender.get_source_display(), + "TENDER_ADMIN_URL": tender_admin_url, } email_body = render_to_string("tenders/create_notification_email_admin_body.txt", data_to_send) send_mail_async( @@ -521,11 +535,13 @@ def send_tenders_author_feedback_or_survey(tender: Tender, kind="feedback_30d"): recipient_name = tender.author.full_name variables = { - "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, + "TENDER_ID": tender.id, "TENDER_TITLE": tender.title, "TENDER_VALIDATE_AT": tender.first_sent_at.strftime("%d %B %Y"), # TODO: TENDER_SENT_AT? "TENDER_KIND": tender.get_kind_display(), "TENDER_KIND_LOWER": tender.get_kind_display().lower(), + "TENDER_AUTHOR_ID": tender.author.id, + "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, } if kind in ["transactioned_question_7d", "transactioned_question_7d_reminder"]: @@ -594,11 +610,15 @@ def send_tenders_siae_survey(tendersiae: TenderSiae, kind="transactioned_questio recipient_name = user.full_name variables = { - "TENDER_AUTHOR_FULL_NAME": tendersiae.tender.contact_full_name, - "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, + "SIAE_ID": tendersiae.siae.id, + "TENDER_ID": tendersiae.tender.id, "TENDER_TITLE": tendersiae.tender.title, "TENDER_VALIDATE_AT": tendersiae.tender.first_sent_at.strftime("%d %B %Y"), # TODO: TENDER_SENT_AT? "TENDER_KIND": tendersiae.tender.get_kind_display(), + "TENDER_KIND_LOWER": tendersiae.tender.get_kind_display().lower(), + "TENDER_AUTHOR_ID": tendersiae.tender.author.id, + "TENDER_AUTHOR_FULL_NAME": tendersiae.tender.contact_full_name, + "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, } user_sesame_query_string = sesame_get_query_string(user) # TODO: sesame scope parameter @@ -638,12 +658,15 @@ def notify_admin_siae_wants_cocontracting(tender: Tender, siae: Siae): email_body = render_to_string( "tenders/cocontracting_notification_email_admin_body.txt", { - "tender_title": tender.title, - "tender_kind": tender.get_kind_display(), - "tender_admin_url": tender_admin_url, - "siae_name": siae.name, - "siae_contact_email": siae.contact_email, - "siae_siret": siae.siret, + "TENDER_ID": tender.id, + "TENDER_TITLE": tender.title, + "TENDER_KIND": tender.get_kind_display(), + "TENDER_KIND_LOWER": tender.get_kind_display().lower(), + "TENDER_ADMIN_URL": tender_admin_url, + "SIAE_ID": siae.id, + "SIAE_NAME": siae.name, + "SIAE_CONTACT_EMAIL": siae.contact_email, + "SIAE_SIRET": siae.siret, }, ) send_mail_async( @@ -666,16 +689,20 @@ def send_super_siaes_email_to_author(tender: Tender, top_siaes: list[Siae]): # Use transaction parameters of Brevo with loop for siaes, documentation : # https://help.brevo.com/hc/en-us/articles/4402386448530-Customize-your-emails-using-transactional-parameters variables = { - "author_name": recipient_name, - "tender_title": tender.title, - "tender_kind": tender.get_kind_display().lower(), - "siaes_count": len(top_siaes), - "siaes": [], - "tender_siae_interested_list_url": f"{get_object_share_url(tender)}/prestataires", + "TENDER_ID": tender.id, + "TENDER_TITLE": tender.title, + "TENDER_KIND": tender.get_kind_display().lower(), + "TENDER_KIND_LOWER": tender.get_kind_display().lower(), + "TENDER_AUTHOR_ID": tender.author.id, + "TENDER_AUTHOR_NAME": recipient_name, + "SIAES_COUNT": len(top_siaes), + "SIAES": [], + "TENDER_SIAE_INTERESTED_LIST_URL": f"{get_object_share_url(tender)}/prestataires", } for siae in top_siaes: variables["siaes"].append( { + "id": siae.id, "name": siae.name_display, "kind": siae.get_kind_display(), "contact_name": siae.contact_full_name,