From 0ce5844720b6810b2174d11194d045eede5011d3 Mon Sep 17 00:00:00 2001 From: Gaspard Lonchampt Date: Tue, 3 Dec 2024 17:16:53 +0100 Subject: [PATCH] feat(invitation_email): add conditionnal rendering for new template --- app/domain/company.py | 24 ++++------- app/helpers/mail.py | 25 ++++++++--- app/helpers/mail_type.py | 1 + .../emails/bizdev/send_invitation_emails.py | 4 +- app/templates/invitation_email.html | 40 ++++++++--------- .../test_find_employee_for_invitation.py | 43 ------------------- 6 files changed, 51 insertions(+), 86 deletions(-) delete mode 100644 app/tests/bizdev/test_find_employee_for_invitation.py diff --git a/app/domain/company.py b/app/domain/company.py index fa54c8b5..ae7c388d 100644 --- a/app/domain/company.py +++ b/app/domain/company.py @@ -5,6 +5,7 @@ from sqlalchemy import exists, and_ from sqlalchemy import func, or_ from sqlalchemy.sql.functions import now +from sqlalchemy.orm import joinedload from app import db from app.helpers.mail_type import EmailType @@ -367,19 +368,15 @@ def find_admins_still_without_invitations( def find_employee_for_invitation( first_employee_invitation_date, companies_to_exclude=None ): + return ( - db.session.query( - Employment.id, - Employment.creation_time, - Employment.has_admin_rights, - Employment.user_id, - Employment.company_id, - ) + db.session.query(Employment) + .options(joinedload(Employment.company)) .join(Email, Email.employment_id == Employment.id) .filter( Email.type == EmailType.INVITATION, Email.user_id.is_(None), - Employment.creation_time + Email.creation_time <= datetime.datetime.combine( first_employee_invitation_date, datetime.datetime.max.time(), @@ -387,14 +384,9 @@ def find_employee_for_invitation( Employment.has_admin_rights == False, Employment.user_id.is_(None), Employment.company_id.notin_(companies_to_exclude or []), + Employment.validation_status + == EmploymentRequestValidationStatus.PENDING, ) - .with_entities( - Employment.id, - Employment.creation_time, - Employment.has_admin_rights, - Employment.user_id, - Employment.company_id, - ) - .yield_per(100) + .yield_per(1000) .all() ) diff --git a/app/helpers/mail.py b/app/helpers/mail.py index 0a7da900..d8e1dbac 100644 --- a/app/helpers/mail.py +++ b/app/helpers/mail.py @@ -366,7 +366,9 @@ def remove_email_from_contact_list(self, email, contact_list): email, contact_list, action=MailjetSubscriptionActions.REMOVE ) - def generate_employee_invite(self, employment, reminder=False): + def generate_employee_invite( + self, employment, reminder=False, scheduled_reminder=False + ): if not employment.invite_token: raise ValueError( f"Cannot send invite for employment {employment} : it is already bound to a user" @@ -379,12 +381,18 @@ def generate_employee_invite(self, employment, reminder=False): invitation_link = f"{app.config['FRONTEND_URL']}/invite?token={employment.invite_token}" company_name = employment.company.name - subject = f"{'Rappel : ' if reminder else ''}{company_name} vous invite à rejoindre Mobilic." + subject = ( + f"{'Rappel : Urgent ! ' if scheduled_reminder else ''}" + f"{'Rappel : ' if reminder else ''}" + f"Votre entreprise {company_name} vous invite à rejoindre Mobilic." + ) return Mailer._create_message_from_flask_template( - "invitation_email.html", + template="invitation_email.html", subject=subject, - type_=EmailType.INVITATION, + type_=EmailType.SCHEDULED_INVITATION + if scheduled_reminder + else EmailType.INVITATION, recipient=employment.user.email if employment.user else employment.email, @@ -395,6 +403,7 @@ def generate_employee_invite(self, employment, reminder=False): invitation_link=Markup(invitation_link), company_name=company_name, reminder=reminder, + scheduled_reminder=scheduled_reminder, ) def send_employee_invite(self, employment, reminder=False): @@ -403,9 +412,13 @@ def send_employee_invite(self, employment, reminder=False): _disable_commit=True, ) - def batch_send_employee_invites(self, employments, reminder=False): + def batch_send_employee_invites( + self, employments, reminder=False, scheduled_reminder=False + ): messages = [ - self.generate_employee_invite(e, reminder=reminder) + self.generate_employee_invite( + e, reminder=reminder, scheduled_reminder=scheduled_reminder + ) for e in employments ] self.send_batch(messages, _disable_commit=True) diff --git a/app/helpers/mail_type.py b/app/helpers/mail_type.py index 3f630bdf..ea3b5b33 100644 --- a/app/helpers/mail_type.py +++ b/app/helpers/mail_type.py @@ -6,6 +6,7 @@ class EmailType(str, Enum): COMPANY_CREATION = "company_creation" EMPLOYMENT_VALIDATION = "employment_validation_confirmation" INVITATION = "invitation" + SCHEDULED_INVITATION = "scheduled_invitation" MISSION_CHANGES_WARNING = "mission_changes_warning" NEW_MISSION_INFORMATION = "new_mission_information" RESET_PASSWORD = "reset_password" diff --git a/app/jobs/emails/bizdev/send_invitation_emails.py b/app/jobs/emails/bizdev/send_invitation_emails.py index 722af6d9..d6f660a2 100644 --- a/app/jobs/emails/bizdev/send_invitation_emails.py +++ b/app/jobs/emails/bizdev/send_invitation_emails.py @@ -20,7 +20,9 @@ def send_invitation_emails(today): if employments: try: - mailer.batch_send_employee_invites(employments, reminder=True) + mailer.batch_send_employee_invites( + employments, reminder=False, scheduled_reminder=True + ) app.logger.info(f"Emails sent for {len(employments)} employments.") except Exception as e: app.logger.error("Error during batch email sending.") diff --git a/app/templates/invitation_email.html b/app/templates/invitation_email.html index a975e756..2e202415 100644 --- a/app/templates/invitation_email.html +++ b/app/templates/invitation_email.html @@ -1,32 +1,32 @@ {% extends "transactional_base.html" %} {% import 'button.html' as button %} -{% block subject %} -{{ company_name }} vous invite à rejoindre Mobilic -{% endblock %} - {% block body %} -

Bonjour{% if first_name %} {{first_name | capitalize}}{% endif %},

- {% if not first_name %} +

Bonjour{% if first_name %} {{ first_name | capitalize }}{% endif %},

+ {% if scheduled_reminder %} +

L'entreprise {{ company_name | upper }} vous rappelle que vous avez été invité à créer votre compte + sur Mobilic, l'outil numérique pour suivre et protéger vos droits en tant que salarié.

+

Grâce à Mobilic, vous pourrez facilement :

+ +

Il vous suffit de quelques clics pour activer votre compte et être prêt(e) à l'utiliser !

+

Cliquez sur le bouton ci-dessous pour créer votre compte ou l'associer à {{ company_name | upper }} :

+ {{ button.button('Activer mon compte', invitation_link) }} +

Petit rappel important : L’enregistrement de votre temps de travail via Mobilic ou le livret + individuel de contrôle (LIC) est obligatoire dans votre secteur.

+

À très bientôt sur Mobilic !

+ {% else %}

{% if reminder %} - L'entreprise {{company_name | upper}} vous rappelle que vous avez été invité + L'entreprise {{ company_name | upper }} vous rappelle que vous avez été invité {% else %} - Vous avez été invité(e) par l’entreprise {{company_name | upper}} + Vous avez été invité(e) par l’entreprise {{ company_name | upper }} {% endif %} à créer un compte Mobilic pour enregistrer votre temps de travail.

Mobilic est la plateforme gouvernementale qui simplifie l'enregistrement et le suivi du temps de travail des travailleurs mobiles du transport routier léger et du déménagement.

-

Pour créer votre compte ou rattacher votre compte existant à l'entreprise {{company_name | upper}} cliquez sur le bouton d'activation suivant :

- {{button.button('Activer mon compte', invitation_link)}} - {% else %} -

- {% if reminder %} - L'entreprise {{company_name | upper}} vous rappelle que vous avez été invité à la rejoindre - {% else %} - Vous avez été invité(e) à rejoindre l'entreprise {{company_name | upper}} - {% endif %} sur Mobilic. -

-

Pour rattacher votre compte à l'entreprise {{company_name | upper}} cliquez sur le bouton d'activation suivant :

- {{button.button('Activer mon compte', invitation_link)}} +

Pour créer votre compte ou rattacher votre compte existant à l'entreprise {{ company_name | upper }} cliquez sur le bouton d'activation suivant :

+ {{ button.button('Activer mon compte', invitation_link) }} {% endif %}

Bien à vous,

{% endblock %} diff --git a/app/tests/bizdev/test_find_employee_for_invitation.py b/app/tests/bizdev/test_find_employee_for_invitation.py deleted file mode 100644 index c468113e..00000000 --- a/app/tests/bizdev/test_find_employee_for_invitation.py +++ /dev/null @@ -1,43 +0,0 @@ -import unittest -import datetime -from app.models import Employment, Email, Company, EmailType -from app import db -from app.domain.company import find_employee_for_invitation - - -class TestFindEmployeeForInvitation(unittest.TestCase): - def setUp(self): - self.session = db.session - - self.company = Company(name="Test Company") - self.employment = Employment( - creation_time=datetime.datetime.now() - - datetime.timedelta(days=10), - has_admin_rights=False, - user_id=None, - company=self.company, - ) - self.email = Email( - type=EmailType.INVITATION, user_id=None, employment=self.employment - ) - - self.session.add(self.company) - self.session.add(self.employment) - self.session.add(self.email) - self.session.commit() - - def tearDown(self): - self.session.query(Email).delete() - self.session.query(Employment).delete() - self.session.query(Company).delete() - self.session.commit() - - def test_find_employee_for_invitation(self): - result = find_employee_for_invitation(datetime.datetime.now()) - - self.assertEqual(len(result), 1) - self.assertEqual(result[0].id, self.employment.id) - - -if __name__ == "__main__": - unittest.main()