diff --git a/config/settings/base.py b/config/settings/base.py index e5c305b23..b94da5484 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -331,24 +331,8 @@ # Transactional email templates # -- tender: siae & partners -MAILJET_TENDERS_SIAE_PRESENTATION_TEMPLATE_ID = env.int("MAILJET_TENDERS_SIAE_PRESENTATION_TEMPLATE_ID", 3679205) MAILJET_TENDERS_PARTNER_PRESENTATION_TEMPLATE_ID = env.int("MAILJET_TENDERS_PARTNER_PRESENTATION_TEMPLATE_ID", 3868179) -MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_2D_TEMPLATE_ID = env.int( - "MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_2D_TEMPLATE_ID", 4716371 -) -MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_3D_TEMPLATE_ID = env.int( - "MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_3D_TEMPLATE_ID", 4716387 -) -MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_4D_TEMPLATE_ID = env.int( - "MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_4D_TEMPLATE_ID", 4716426 -) -MAILJET_TENDERS_SIAE_INTERESTED_REMINDER_2D_TEMPLATE_ID = env.int( - "MAILJET_TENDERS_SIAE_INTERESTED_REMINDER_2D_TEMPLATE_ID", 4744896 -) # -- tender: author -MAILJET_TENDERS_AUTHOR_CONFIRMATION_VALIDATED_TEMPLATE_ID = env.int( - "MAILJET_TENDERS_AUTHOR_CONFIRMATION_VALIDATED_TEMPLATE_ID", 3896680 -) MAILJET_TENDERS_AUTHOR_SIAE_INTERESTED_1_TEMPLATE_ID = env.int( "MAILJET_TENDERS_AUTHOR_SIAE_INTERESTED_1_TEMPLATE_ID", 3867188 ) diff --git a/lemarche/conversations/models.py b/lemarche/conversations/models.py index 526d59dec..4c1ab801a 100644 --- a/lemarche/conversations/models.py +++ b/lemarche/conversations/models.py @@ -247,7 +247,7 @@ def __str__(self): @property def get_template_id(self): - if self.is_active and self.source and self.code: + if self.source and self.code: if self.source == conversation_constants.SOURCE_MAILJET: return self.mailjet_id elif self.source == conversation_constants.SOURCE_BREVO: @@ -263,23 +263,24 @@ def send_transactional_email( from_email=settings.DEFAULT_FROM_EMAIL, from_name=settings.DEFAULT_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, - ) - 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, - ) + if self.is_active: + 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, + ) + 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, + ) diff --git a/lemarche/conversations/tests.py b/lemarche/conversations/tests.py index dfb7d64a0..266e473db 100644 --- a/lemarche/conversations/tests.py +++ b/lemarche/conversations/tests.py @@ -95,7 +95,7 @@ def setUpTestData(cls): ) def test_get_template_id(self): - self.assertIsNone(self.tt_inactive.get_template_id) self.assertIsNone(self.tt_active_empty.get_template_id) + self.assertEqual(self.tt_inactive.get_template_id, self.tt_inactive.mailjet_id) self.assertEqual(self.tt_active_mailjet.get_template_id, self.tt_active_mailjet.mailjet_id) self.assertEqual(self.tt_active_brevo.get_template_id, self.tt_active_brevo.brevo_id) diff --git a/lemarche/siaes/models.py b/lemarche/siaes/models.py index 30e35e8fc..e3c159003 100644 --- a/lemarche/siaes/models.py +++ b/lemarche/siaes/models.py @@ -1083,6 +1083,10 @@ def contact_short_name(self): return f"{self.contact_first_name.upper()[:1]}. {self.contact_last_name.upper()}" return "" + @property + def contact_email_name_display(self): + return self.contact_full_name or self.name_display + @property def contact_phone_display(self): return phone_number_display(self.contact_phone) diff --git a/lemarche/www/conversations/tasks.py b/lemarche/www/conversations/tasks.py index 11447b7de..5f7875884 100644 --- a/lemarche/www/conversations/tasks.py +++ b/lemarche/www/conversations/tasks.py @@ -11,7 +11,8 @@ def send_first_email_from_conversation(conv: Conversation): siae: Siae = conv.siae - from_email = f"{conv.sender_first_name} {conv.sender_last_name} <{conv.sender_email_buyer_encoded}>" + from_name = f"{conv.sender_first_name} {conv.sender_last_name}" + from_email = f"{from_name} <{conv.sender_email_buyer_encoded}>" sender_company_name = "" if conv.sender_user and conv.sender_user.company_name: @@ -38,7 +39,8 @@ def send_email_from_conversation( ): if user_kind == Conversation.USER_KIND_SENDER_TO_SIAE: # from the buyer to the siae - from_email = f"{conv.sender_first_name} {conv.sender_last_name} <{conv.sender_email_buyer_encoded}>" + from_name = f"{conv.sender_first_name} {conv.sender_last_name}" + from_email = f"{from_name} <{conv.sender_email_buyer_encoded}>" send_mail_async( email_subject=email_subject, email_body=email_body + DISCLAIMER_ATTACHMENTS, @@ -49,7 +51,7 @@ def send_email_from_conversation( elif user_kind == Conversation.USER_KIND_SENDER_TO_BUYER: # from the siae to the buyer siae: Siae = conv.siae - from_email = f"{siae.contact_full_name} <{conv.sender_email_siae_encoded}>" + from_email = f"{siae.contact_email_name_display} <{conv.sender_email_siae_encoded}>" send_mail_async( email_subject=email_subject, email_body=email_body + DISCLAIMER_ATTACHMENTS, diff --git a/lemarche/www/tenders/tasks.py b/lemarche/www/tenders/tasks.py index 17635f372..243ddfa61 100644 --- a/lemarche/www/tenders/tasks.py +++ b/lemarche/www/tenders/tasks.py @@ -7,6 +7,7 @@ from django.utils import timezone from sesame.utils import get_query_string as sesame_get_query_string +from lemarche.conversations.models import TemplateTransactional from lemarche.siaes.models import Siae from lemarche.tenders import constants as tender_constants from lemarche.tenders.models import PartnerShareTender, Tender, TenderSiae @@ -25,7 +26,7 @@ def send_validated_tender(tender: Tender): # find the matching Siaes? done in Tender post_save signal # notify author # TODO: we still notify author for each send ? - send_confirmation_published_email_to_author(tender, nb_matched_siaes=tender.siaes.count()) + send_confirmation_published_email_to_author(tender) # send the tender to all matching Siaes & Partners send_tender_emails_to_siaes(tender) send_tender_emails_to_partners(tender) @@ -113,6 +114,60 @@ def send_tender_emails_to_siaes(tender: Tender): tender.save() +# @task() +def send_tender_email_to_siae(tender: Tender, siae: Siae, email_subject: str, recipient_to_override: User = None): + email_template = TemplateTransactional.objects.get(code="TENDERS_SIAE_PRESENTATION") + # override siae.contact_email if email_to_override is provided + email_to = recipient_to_override.email if recipient_to_override else siae.contact_email + recipient_list = whitelist_recipient_list([email_to]) + if len(recipient_list): + recipient_email = recipient_list[0] + recipient_name = siae.contact_email_name_display + + tender_url = f"{get_object_share_url(tender)}?siae_id={siae.id}" + tender_not_interested_url = f"{get_object_share_url(tender)}?siae_id={siae.id}¬_interested=True" + if recipient_to_override: + tender_url += f"&user_id={recipient_to_override.id}" + tender_not_interested_url += f"&user_id={recipient_to_override.id}" + + variables = { + "SIAE_CONTACT_FIRST_NAME": siae.contact_first_name, + "SIAE_SECTORS": siae.sectors_list_string(), + "SIAE_PERIMETER": siae.geo_range_pretty_display, + "TENDER_TITLE": tender.title, + "TENDER_AUTHOR_COMPANY": tender.author.company_name, + "TENDER_KIND": tender.get_kind_display(), + "TENDER_SECTORS": tender.sectors_list_string(), + "TENDER_PERIMETERS": tender.location_display, + "TENDER_AMOUNT": tender.amount_display, + "TENDER_DEADLINE_DATE": date_to_string(tender.deadline_date), + "TENDER_URL": tender_url, + "TENDER_NOT_INTERESTED_URL": tender_not_interested_url, + } + + email_template.send_transactional_email( + recipient_email=recipient_email, + recipient_name=recipient_name, + variables=variables, + subject=email_subject, + from_email=settings.DEFAULT_FROM_EMAIL, + from_name=settings.DEFAULT_FROM_NAME, + ) + + # update tendersiae + tendersiae = TenderSiae.objects.get(tender=tender, siae=siae) + tendersiae.email_send_date = timezone.now() + log_item = { + "action": "email_sent", + "email_template": email_template.code, + "email_to": recipient_email, + "email_subject": email_subject, + "email_timestamp": timezone.now().isoformat(), + } + tendersiae.logs.append(log_item) + tendersiae.save() + + def send_tender_emails_to_partners(tender: Tender): """ All corresponding partners (PartnerShareTender) will be contacted @@ -153,8 +208,8 @@ def send_tender_email_to_partner(email_subject: str, tender: Tender, partner: Pa subject=email_subject, recipient_email_list=recipient_list, variables=variables, - from_email=settings.TEAM_CONTACT_EMAIL, - from_name="Pauline du Marché de l'inclusion", + from_email=settings.DEFAULT_FROM_EMAIL, + from_name=settings.DEFAULT_FROM_NAME, ) # log email @@ -174,71 +229,15 @@ def send_tender_email_to_partner(email_subject: str, tender: Tender, partner: Pa partner.save() -# @task() -def send_tender_email_to_siae(tender: Tender, siae: Siae, email_subject: str, recipient_to_override: User = None): - # override siae.contact_email if email_to_override is provided - email_to = recipient_to_override.email if recipient_to_override else siae.contact_email - recipient_list = whitelist_recipient_list([email_to]) - if recipient_list: - recipient_email = recipient_list[0] if recipient_list else "" - recipient_name = siae.contact_full_name - - tender_url = f"{get_object_share_url(tender)}?siae_id={siae.id}" - tender_not_interested_url = f"{get_object_share_url(tender)}?siae_id={siae.id}¬_interested=True" - if recipient_to_override: - tender_url += f"&user_id={recipient_to_override.id}" - tender_not_interested_url += f"&user_id={recipient_to_override.id}" - - variables = { - "SIAE_CONTACT_FIRST_NAME": siae.contact_first_name, - "SIAE_SECTORS": siae.sectors_list_string(), - "SIAE_PERIMETER": siae.geo_range_pretty_display, - "TENDER_TITLE": tender.title, - "TENDER_AUTHOR_COMPANY": tender.author.company_name, - "TENDER_KIND": tender.get_kind_display(), - "TENDER_SECTORS": tender.sectors_list_string(), - "TENDER_PERIMETERS": tender.location_display, - "TENDER_AMOUNT": tender.amount_display, - "TENDER_DEADLINE_DATE": date_to_string(tender.deadline_date), - "TENDER_URL": tender_url, - "TENDER_NOT_INTERESTED_URL": tender_not_interested_url, - } - - api_mailjet.send_transactional_email_with_template( - template_id=settings.MAILJET_TENDERS_SIAE_PRESENTATION_TEMPLATE_ID, - recipient_email=recipient_email, - recipient_name=recipient_name, - variables=variables, - subject=email_subject, - from_email=settings.TEAM_CONTACT_EMAIL, - from_name="Pauline du Marché de l'inclusion", - ) - - # update tendersiae - tendersiae = TenderSiae.objects.get(tender=tender, siae=siae) - tendersiae.email_send_date = timezone.now() - log_item = { - "action": "email_sent", - "email_to": recipient_email, - "email_subject": email_subject, - "email_timestamp": timezone.now().isoformat(), - } - tendersiae.logs.append(log_item) - tendersiae.save() - - def send_tender_contacted_reminder_email_to_siaes( tender: Tender, days_since_email_send_date=2, send_on_weekends=False ): if days_since_email_send_date == 2: - email_subject = f"Un {tender.get_kind_display().lower()} pour vous sur le Marché de l'inclusion" - template_id = settings.MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_2D_TEMPLATE_ID + email_template = TemplateTransactional.objects.get(code="TENDERS_SIAE_CONTACTED_REMINDER_2D") elif days_since_email_send_date == 3: - email_subject = f"Avez vous consulté le {tender.get_kind_display().lower()} ?" - template_id = settings.MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_3D_TEMPLATE_ID + email_template = TemplateTransactional.objects.get(code="TENDERS_SIAE_CONTACTED_REMINDER_3D") elif days_since_email_send_date == 4: - email_subject = f"L'opportunité : {tender.get_kind_display().lower()} a besoin de votre réponse !" - template_id = settings.MAILJET_TENDERS_SIAE_CONTACTED_REMINDER_4D_TEMPLATE_ID + email_template = TemplateTransactional.objects.get(code="TENDERS_SIAE_CONTACTED_REMINDER_4D") else: error_message = f"send_tender_contacted_reminder_email_to_siaes: days_since_email_send_date has a non-managed value ({days_since_email_send_date})" # noqa raise Exception(error_message) @@ -257,14 +256,12 @@ def send_tender_contacted_reminder_email_to_siaes( for tendersiae in tendersiae_contacted_reminder_list: # send to siae 'contact_email' - send_tender_contacted_reminder_email_to_siae( - tendersiae, email_subject, template_id, days_since_email_send_date - ) + send_tender_contacted_reminder_email_to_siae(tendersiae, email_template, days_since_email_send_date) # log email batch log_item = { "action": f"email_siaes_contacted_reminder_{days_since_email_send_date}d", - "email_subject": email_subject, + "email_template": email_template.code, "email_count": tendersiae_contacted_reminder_list.count(), "email_timestamp": timezone.now().isoformat(), } @@ -272,13 +269,11 @@ def send_tender_contacted_reminder_email_to_siaes( tender.save() -def send_tender_contacted_reminder_email_to_siae( - tendersiae: TenderSiae, email_subject, template_id, days_since_email_send_date -): +def send_tender_contacted_reminder_email_to_siae(tendersiae: TenderSiae, email_template, days_since_email_send_date): recipient_list = whitelist_recipient_list([tendersiae.siae.contact_email]) - if recipient_list: - recipient_email = recipient_list[0] if recipient_list else "" - recipient_name = tendersiae.tender.author.full_name + if len(recipient_list): + recipient_email = recipient_list[0] + recipient_name = tendersiae.siae.contact_email_name_display variables = { "SIAE_CONTACT_FIRST_NAME": tendersiae.siae.contact_first_name, @@ -287,6 +282,7 @@ def send_tender_contacted_reminder_email_to_siae( "TENDER_TITLE": tendersiae.tender.title, "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, "TENDER_KIND": tendersiae.tender.get_kind_display(), + "TENDER_KIND_LOWER": tendersiae.tender.get_kind_display().lower(), "TENDER_SECTORS": tendersiae.tender.sectors_list_string(), "TENDER_PERIMETERS": tendersiae.tender.location_display, "TENDER_AMOUNT": tendersiae.tender.amount_display, @@ -294,19 +290,19 @@ def send_tender_contacted_reminder_email_to_siae( "TENDER_URL": f"{get_object_share_url(tendersiae.tender)}?siae_id={tendersiae.siae.id}&mtm_campaign=relance-esi-contactees", # noqa } - api_mailjet.send_transactional_email_with_template( - template_id=template_id, + email_template.send_transactional_email( recipient_email=recipient_email, recipient_name=recipient_name, variables=variables, - subject=email_subject, + from_email=settings.DEFAULT_FROM_EMAIL, + from_name=settings.DEFAULT_FROM_NAME, ) # log email log_item = { "action": f"email_siae_contacted_reminder_{days_since_email_send_date}d", + "email_template": email_template.code, "email_to": recipient_email, - "email_subject": email_subject, # "email_body": email_body, "email_timestamp": timezone.now().isoformat(), } @@ -317,7 +313,7 @@ def send_tender_contacted_reminder_email_to_siae( def send_tender_interested_reminder_email_to_siaes( tender: Tender, days_since_detail_contact_click_date=2, send_on_weekends=False ): - email_subject = f"{tender.title}" + email_template = TemplateTransactional.objects.get(code="TENDERS_SIAE_INTERESTED_REMINDER_2D") current_weekday = timezone.now().weekday() @@ -333,12 +329,12 @@ def send_tender_interested_reminder_email_to_siaes( for tendersiae in tendersiae_interested_reminder_list: # send to siae 'contact_email' - send_tender_interested_reminder_email_to_siae(tendersiae, email_subject, days_since_detail_contact_click_date) + send_tender_interested_reminder_email_to_siae(tendersiae, email_template, days_since_detail_contact_click_date) # log email batch log_item = { "action": f"email_siaes_interested_reminder_{days_since_detail_contact_click_date}d", - "email_subject": email_subject, + "email_template": email_template.code, "email_count": tendersiae_interested_reminder_list.count(), "email_timestamp": timezone.now().isoformat(), } @@ -347,12 +343,12 @@ def send_tender_interested_reminder_email_to_siaes( def send_tender_interested_reminder_email_to_siae( - tendersiae: TenderSiae, email_subject, days_since_detail_contact_click_date + tendersiae: TenderSiae, email_template, days_since_detail_contact_click_date ): recipient_list = whitelist_recipient_list([tendersiae.siae.contact_email]) - if recipient_list: - recipient_email = recipient_list[0] if recipient_list else "" - recipient_name = tendersiae.tender.author.full_name + if len(recipient_list): + recipient_email = recipient_list[0] + recipient_name = tendersiae.siae.contact_email_name_display variables = { "SIAE_CONTACT_FIRST_NAME": tendersiae.siae.contact_first_name, @@ -361,6 +357,7 @@ def send_tender_interested_reminder_email_to_siae( "TENDER_TITLE": tendersiae.tender.title, "TENDER_AUTHOR_COMPANY": tendersiae.tender.author.company_name, "TENDER_KIND": tendersiae.tender.get_kind_display(), + "TENDER_KIND_LOWER": tendersiae.tender.get_kind_display().lower(), "TENDER_SECTORS": tendersiae.tender.sectors_list_string(), "TENDER_PERIMETERS": tendersiae.tender.location_display, "TENDER_AMOUNT": tendersiae.tender.amount_display, @@ -368,19 +365,19 @@ def send_tender_interested_reminder_email_to_siae( "TENDER_URL": f"{get_object_share_url(tendersiae.tender)}?siae_id={tendersiae.siae.id}&mtm_campaign=relance-esi-interessees", # noqa } - api_mailjet.send_transactional_email_with_template( - template_id=settings.MAILJET_TENDERS_SIAE_INTERESTED_REMINDER_2D_TEMPLATE_ID, + email_template.send_transactional_email( recipient_email=recipient_email, recipient_name=recipient_name, variables=variables, - subject=email_subject, + from_email=settings.DEFAULT_FROM_EMAIL, + from_name=settings.DEFAULT_FROM_NAME, ) # log email log_item = { "action": f"email_siae_interested_reminder_{days_since_detail_contact_click_date}d", + "email_template": email_template.code, "email_to": recipient_email, - "email_subject": email_subject, # "email_body": email_body, "email_timestamp": timezone.now().isoformat(), } @@ -388,49 +385,46 @@ def send_tender_interested_reminder_email_to_siae( tendersiae.save() -def send_confirmation_published_email_to_author(tender: Tender, nb_matched_siaes: int): - """Send email to the author when the tender is published to the siaes - - Args: - tender (Tender): Tender published - nb_matched (int): number of siaes match +def send_confirmation_published_email_to_author(tender: Tender): """ - email_subject = f"Votre {tender.get_kind_display().lower()} a été publié !" - recipient_list = whitelist_recipient_list([tender.author.email]) - if recipient_list and not tender.contact_notifications_disabled: - recipient_email = recipient_list[0] if recipient_list else "" - recipient_name = tender.author.full_name + Send email to the author when the tender is published to the siaes + """ + if not tender.contact_notifications_disabled: + email_template = TemplateTransactional.objects.get(code="TENDERS_AUTHOR_CONFIRMATION_VALIDATED") + recipient_list = whitelist_recipient_list([tender.author.email]) + if len(recipient_list): + recipient_email = recipient_list[0] + recipient_name = tender.author.full_name - variables = { - "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, - "TENDER_TITLE": tender.title, - "TENDER_KIND": tender.get_kind_display(), - "TENDER_SECTORS": tender.sectors_list_string(), - "TENDER_PERIMETERS": tender.location_display, - "TENDER_AMOUNT": tender.amount_display, - "TENDER_DEADLINE_DATE": date_to_string(tender.deadline_date), - "TENDER_NB_MATCH": nb_matched_siaes, - "TENDER_URL": get_object_share_url(tender), - } + variables = { + "TENDER_AUTHOR_FIRST_NAME": tender.author.first_name, + "TENDER_TITLE": tender.title, + "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, + "TENDER_DEADLINE_DATE": date_to_string(tender.deadline_date), + "TENDER_NB_MATCH": tender.siaes.count(), + "TENDER_URL": get_object_share_url(tender), + } - api_mailjet.send_transactional_email_with_template( - template_id=settings.MAILJET_TENDERS_AUTHOR_CONFIRMATION_VALIDATED_TEMPLATE_ID, - recipient_email=recipient_email, - recipient_name=recipient_name, - variables=variables, - subject=email_subject, - ) + email_template.send_transactional_email( + recipient_email=recipient_email, + recipient_name=recipient_name, + variables=variables, + ) - # log email - log_item = { - "action": "email_publish_confirmation", - "email_to": recipient_email, - "email_subject": email_subject, - # "email_body": email_body, - "email_timestamp": timezone.now().isoformat(), - } - tender.logs.append(log_item) - tender.save() + # log email + log_item = { + "action": "email_publish_confirmation", + "email_template": email_template.code, + "email_to": recipient_email, + # "email_body": email_body, + "email_timestamp": timezone.now().isoformat(), + } + tender.logs.append(log_item) + tender.save() def send_siae_interested_email_to_author(tender: Tender):