From b31beb2eb08ff1a2b7107a4f95548a366db1c818 Mon Sep 17 00:00:00 2001 From: Quentin Loridant Date: Mon, 28 Oct 2024 14:59:47 +0100 Subject: [PATCH 1/4] =?UTF-8?q?Remplacer=20le=20niveau=20de=20logging=20d?= =?UTF-8?q?=20Exception=20=C3=A0=20Warning=20quand=20un=20batch=20ne=20peu?= =?UTF-8?q?t=20pas=20=C3=AAtre=20updat=C3=A9=20car=20un=20des=20contact=20?= =?UTF-8?q?n=20existe=20pas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- macantine/tasks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/macantine/tasks.py b/macantine/tasks.py index f10661172..13dc4a6a1 100644 --- a/macantine/tasks.py +++ b/macantine/tasks.py @@ -194,8 +194,10 @@ def update_brevo_contacts(): for user in chunk: user.last_brevo_update = today user.save() + except requests.exceptions.HTTPError as e: + logger.warning(f"Bulk updating Brevo users: One or more of the users don't exist. {e}") except Exception as e: - logger.exception(f"Error bulk updating Brevo users {e}", stack_info=True) + logger.exception(f"Bulk updating Brevo users: Error updating Brevo users {e}", stack_info=True) time.sleep(0.1) # API rate limit is 10 req per second # Try creating those who didn't make it (allowing the update flag to be set) From c67a138a859102ff73663b62ae3a183cde2c4420 Mon Sep 17 00:00:00 2001 From: Quentin Loridant Date: Mon, 28 Oct 2024 17:46:51 +0100 Subject: [PATCH 2/4] Rfeacto brevo tasks --- macantine/brevo.py | 87 ++++++++++++++++++++++++ macantine/tasks.py | 86 +++-------------------- macantine/tests/test_automatic_emails.py | 36 +++++----- 3 files changed, 115 insertions(+), 94 deletions(-) create mode 100644 macantine/brevo.py diff --git a/macantine/brevo.py b/macantine/brevo.py new file mode 100644 index 000000000..2c73b7c70 --- /dev/null +++ b/macantine/brevo.py @@ -0,0 +1,87 @@ +import logging +import time + +import requests +import sib_api_v3_sdk +from django.conf import settings + +from data.models import Canteen + +logger = logging.getLogger(__name__) + +configuration = sib_api_v3_sdk.Configuration() +configuration.api_key["api-key"] = settings.ANYMAIL.get("SENDINBLUE_API_KEY") +api_client = sib_api_v3_sdk.ApiClient(configuration) +email_api_instance = sib_api_v3_sdk.TransactionalEmailsApi(api_client) +contacts_api_instance = sib_api_v3_sdk.ContactsApi(api_client) + + +def send_sib_template(template_id, parameters, to_email, to_name): + send_smtp_email = sib_api_v3_sdk.SendSmtpEmail( + to=[{"email": to_email, "name": to_name}], + params=parameters, + sender={"email": settings.CONTACT_EMAIL, "name": "ma cantine"}, + reply_to={"email": settings.CONTACT_EMAIL, "name": "ma cantine"}, + template_id=template_id, + ) + email_api_instance.send_transac_email(send_smtp_email) + + +def user_to_brevo_payload(user, bulk=True): + has_canteens = user.canteens.exists() + date_joined = user.date_joined + + def missing_diag_for_year(year, user): + return user.canteens.exists() and any(not x.has_diagnostic_for_year(year) for x in user.canteens.all()) + + def missing_td_for_year(year, user): + return user.canteens.exists() and any(not x.has_teledeclaration_for_year(year) for x in user.canteens.all()) + + missing_publications = ( + has_canteens and user.canteens.filter(publication_status=Canteen.PublicationStatus.DRAFT).exists() + ) + + dict_attributes = { + "MA_CANTINE_DATE_INSCRIPTION": date_joined.strftime("%Y-%m-%d"), + "MA_CANTINE_COMPTE_DEV": user.is_dev, + "MA_CANTINE_COMPTE_ELU_E": user.is_elected_official, + "MA_CANTINE_GERE_UN_ETABLISSEMENT": has_canteens, + "MA_CANTINE_MANQUE_BILAN_DONNEES_2023": missing_diag_for_year(2023, user), + "MA_CANTINE_MANQUE_BILAN_DONNEES_2022": missing_diag_for_year(2022, user), + "MA_CANTINE_MANQUE_BILAN_DONNEES_2021": missing_diag_for_year(2021, user), + "MA_CANTINE_MANQUE_TD_DONNEES_2023": missing_td_for_year(2023, user), + "MA_CANTINE_MANQUE_TD_DONNEES_2022": missing_td_for_year(2022, user), + "MA_CANTINE_MANQUE_TD_DONNEES_2021": missing_td_for_year(2021, user), + "MA_CANTINE_MANQUE_PUBLICATION": missing_publications, + } + if bulk: + return sib_api_v3_sdk.UpdateBatchContactsContacts(email=user.email, attributes=dict_attributes) + return sib_api_v3_sdk.CreateContact(email=user.email, attributes=dict_attributes, update_enabled=True) + + +def update_existing_brevo_contacts(users_tu_update, today): + for chunk in users_tu_update: + contacts = [user_to_brevo_payload(user) for user in chunk] + update_object = sib_api_v3_sdk.UpdateBatchContacts(contacts) + try: + contacts_api_instance.update_batch_contacts(update_object) + for user in chunk: + user.last_brevo_update = today + user.save() + except requests.exceptions.HTTPError as e: + logger.warning(f"Bulk updating Brevo users: One or more of the users don't exist. {e}") + except Exception as e: + logger.exception(f"Bulk updating Brevo users: Error updating Brevo users {e}", stack_info=True) + time.sleep(0.1) # API rate limit is 10 req per second + + +def create_new_brevo_users(users_to_create, today): + for user in users_to_create: + try: + contact = user_to_brevo_payload(user, bulk=False) + contacts_api_instance.create_contact(contact) + user.last_brevo_update = today + user.save() + except Exception as e: + logger.exception(f"Error creating/updating an individual Brevo user {e}", stack_info=True) + time.sleep(0.1) # API rate limit is 10 req per second diff --git a/macantine/tasks.py b/macantine/tasks.py index 13dc4a6a1..348938267 100644 --- a/macantine/tasks.py +++ b/macantine/tasks.py @@ -5,7 +5,6 @@ import redis as r import requests -import sib_api_v3_sdk from django.conf import settings from django.core.management import call_command from django.core.paginator import Paginator @@ -18,6 +17,11 @@ from common.utils import get_token_sirene from data.models import Canteen, User +from .brevo import ( + create_new_brevo_users, + send_sib_template, + update_existing_brevo_contacts, +) from .celery import app from .etl.analysis import ETL_ANALYSIS_CANTEEN, ETL_ANALYSIS_TD from .etl.open_data import ETL_OPEN_DATA_CANTEEN, ETL_OPEN_DATA_TD @@ -25,22 +29,6 @@ logger = logging.getLogger(__name__) redis = r.from_url(settings.REDIS_URL, decode_responses=True) -configuration = sib_api_v3_sdk.Configuration() -configuration.api_key["api-key"] = settings.ANYMAIL.get("SENDINBLUE_API_KEY") -api_client = sib_api_v3_sdk.ApiClient(configuration) -email_api_instance = sib_api_v3_sdk.TransactionalEmailsApi(api_client) -contacts_api_instance = sib_api_v3_sdk.ContactsApi(api_client) - - -def _send_sib_template(template_id, parameters, to_email, to_name): - send_smtp_email = sib_api_v3_sdk.SendSmtpEmail( - to=[{"email": to_email, "name": to_name}], - params=parameters, - sender={"email": settings.CONTACT_EMAIL, "name": "ma cantine"}, - reply_to={"email": settings.CONTACT_EMAIL, "name": "ma cantine"}, - template_id=template_id, - ) - email_api_instance.send_transac_email(send_smtp_email) def _user_name(user): @@ -70,7 +58,7 @@ def no_canteen_first_reminder(): try: parameters = {"PRENOM": user.first_name} to_name = _user_name(user) - _send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_FIRST, parameters, user.email, to_name) + send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_FIRST, parameters, user.email, to_name) logger.info(f"First email sent to {user.get_full_name()} ({user.email})") user.email_no_canteen_first_reminder = today user.save() @@ -105,7 +93,7 @@ def no_canteen_second_reminder(): try: parameters = {"PRENOM": user.first_name} to_name = _user_name(user) - _send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_SECOND, parameters, user.email, to_name) + send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_SECOND, parameters, user.email, to_name) logger.info(f"Second email sent to {user.get_full_name()} ({user.email})") user.email_no_canteen_second_reminder = today user.save() @@ -115,38 +103,6 @@ def no_canteen_second_reminder(): logger.exception(f"Unable to send second no-cantine reminder email to {user.username}:\n{e}") -def user_to_brevo_payload(user, bulk=True): - has_canteens = user.canteens.exists() - date_joined = user.date_joined - - def missing_diag_for_year(year, user): - return user.canteens.exists() and any(not x.has_diagnostic_for_year(year) for x in user.canteens.all()) - - def missing_td_for_year(year, user): - return user.canteens.exists() and any(not x.has_teledeclaration_for_year(year) for x in user.canteens.all()) - - missing_publications = ( - has_canteens and user.canteens.filter(publication_status=Canteen.PublicationStatus.DRAFT).exists() - ) - - dict_attributes = { - "MA_CANTINE_DATE_INSCRIPTION": date_joined.strftime("%Y-%m-%d"), - "MA_CANTINE_COMPTE_DEV": user.is_dev, - "MA_CANTINE_COMPTE_ELU_E": user.is_elected_official, - "MA_CANTINE_GERE_UN_ETABLISSEMENT": has_canteens, - "MA_CANTINE_MANQUE_BILAN_DONNEES_2023": missing_diag_for_year(2023, user), - "MA_CANTINE_MANQUE_BILAN_DONNEES_2022": missing_diag_for_year(2022, user), - "MA_CANTINE_MANQUE_BILAN_DONNEES_2021": missing_diag_for_year(2021, user), - "MA_CANTINE_MANQUE_TD_DONNEES_2023": missing_td_for_year(2023, user), - "MA_CANTINE_MANQUE_TD_DONNEES_2022": missing_td_for_year(2022, user), - "MA_CANTINE_MANQUE_TD_DONNEES_2021": missing_td_for_year(2021, user), - "MA_CANTINE_MANQUE_PUBLICATION": missing_publications, - } - if bulk: - return sib_api_v3_sdk.UpdateBatchContactsContacts(email=user.email, attributes=dict_attributes) - return sib_api_v3_sdk.CreateContact(email=user.email, attributes=dict_attributes, update_enabled=True) - - ########################################################################## # Taken from itertools recipes. Will be able to remove once we pass to # Python 3.12 since they added it as itertools.batched. Server is currently @@ -185,34 +141,12 @@ def update_brevo_contacts(): chunks = batched(users_to_update, bulk_update_size) logger.info("update_brevo_contacts batch updating started") - - for chunk in chunks: - contacts = [user_to_brevo_payload(user) for user in chunk] - update_object = sib_api_v3_sdk.UpdateBatchContacts(contacts) - try: - contacts_api_instance.update_batch_contacts(update_object) - for user in chunk: - user.last_brevo_update = today - user.save() - except requests.exceptions.HTTPError as e: - logger.warning(f"Bulk updating Brevo users: One or more of the users don't exist. {e}") - except Exception as e: - logger.exception(f"Bulk updating Brevo users: Error updating Brevo users {e}", stack_info=True) - time.sleep(0.1) # API rate limit is 10 req per second + update_existing_brevo_contacts(chunks, today) # Try creating those who didn't make it (allowing the update flag to be set) users_to_update = User.objects.filter(Q(last_brevo_update__lte=threshold) | Q(last_brevo_update__isnull=True)) logger.info("update_brevo_contacts individual creating/updating started") - - for user in users_to_update: - try: - contact = user_to_brevo_payload(user, bulk=False) - contacts_api_instance.create_contact(contact) - user.last_brevo_update = today - user.save() - except Exception as e: - logger.exception(f"Error creating/updating an individual Brevo user {e}", stack_info=True) - time.sleep(0.1) # API rate limit is 10 req per second + create_new_brevo_users(chunks, today) end = time.time() logger.info(f"update_brevo_contacts task ended. Duration : { end - start } seconds") @@ -244,7 +178,7 @@ def no_diagnostic_first_reminder(): try: parameters = {"PRENOM": manager.first_name, "NOM_CANTINE": canteen.name} to_name = _user_name(manager) - _send_sib_template( + send_sib_template( settings.TEMPLATE_ID_NO_DIAGNOSTIC_FIRST, parameters, manager.email, diff --git a/macantine/tests/test_automatic_emails.py b/macantine/tests/test_automatic_emails.py index ed73393f5..ae13c1d36 100644 --- a/macantine/tests/test_automatic_emails.py +++ b/macantine/tests/test_automatic_emails.py @@ -59,7 +59,7 @@ def test_no_canteen_first_reminder(self, _): tasks.no_canteen_first_reminder() # Email is only sent once to Jean - tasks._send_sib_template.assert_called_once_with( + tasks.send_sib_template.assert_called_once_with( 1, {"PRENOM": "Jean"}, "jean.serien@example.com", "Jean Sérien" ) @@ -94,7 +94,7 @@ def test_no_canteen_dev_profile(self, _): ) tasks.no_canteen_first_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() jean.refresh_from_db() self.assertIsNone(jean.email_no_canteen_first_reminder) @@ -161,7 +161,7 @@ def test_no_canteen_second_reminder(self, _): tasks.no_canteen_second_reminder() # Email is only sent once to Marie - tasks._send_sib_template.assert_called_once_with(2, {"PRENOM": ""}, "marie.olait@example.com", "marie.olait") + tasks.send_sib_template.assert_called_once_with(2, {"PRENOM": ""}, "marie.olait@example.com", "marie.olait") jean.refresh_from_db() anna.refresh_from_db() @@ -193,7 +193,7 @@ def test_no_canteen_second_reminder_dev(self, _): is_dev=True, ) tasks.no_canteen_second_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() marie.refresh_from_db() self.assertIsNone(marie.email_no_canteen_second_reminder) @@ -225,7 +225,7 @@ def test_no_template_settings(self, _): tasks.no_canteen_first_reminder() tasks.no_canteen_second_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() @mock.patch("macantine.tasks._send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=1) @@ -257,16 +257,16 @@ def test_emails_should_only_be_sent_once(self, _): tasks.no_canteen_first_reminder() tasks.no_canteen_first_reminder() tasks.no_canteen_first_reminder() - tasks._send_sib_template.assert_called_once_with( + tasks.send_sib_template.assert_called_once_with( 1, {"PRENOM": "Jean"}, "jean.serien@example.com", "Jean Sérien" ) - tasks._send_sib_template.reset_mock() + tasks.send_sib_template.reset_mock() tasks.no_canteen_second_reminder() tasks.no_canteen_second_reminder() tasks.no_canteen_second_reminder() - tasks._send_sib_template.assert_called_once_with( + tasks.send_sib_template.assert_called_once_with( 2, {"PRENOM": "Marie"}, "marie.olait@example.com", "Marie Olait" ) @@ -356,9 +356,9 @@ def test_no_diagnostic_first_reminder(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Jean - tasks._send_sib_template.assert_called() - self.assertEqual(tasks._send_sib_template.call_count, 2) - call_args_list = tasks._send_sib_template.call_args_list + tasks.send_sib_template.assert_called() + self.assertEqual(tasks.send_sib_template.call_count, 2) + call_args_list = tasks.send_sib_template.call_args_list recipients = [x[0][2] for x in call_args_list] self.assertIn("jean.serien@example.com", recipients) self.assertIn("anna.logue@example.com", recipients) @@ -388,7 +388,7 @@ def test_no_diagnostic_dev_profile(self, _): Canteen.objects.filter(pk=canteen_no_diagnostics.id).update(creation_date=(today - timedelta(weeks=2))) tasks.no_diagnostic_first_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() canteen_no_diagnostics.refresh_from_db() self.assertIsNone(canteen_no_diagnostics.email_no_diagnostic_first_reminder) @@ -413,7 +413,7 @@ def test_email_opt_out_first_reminder(self, _): ) tasks.no_canteen_first_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() self.assertIsNone(jean.email_no_canteen_first_reminder) @@ -438,7 +438,7 @@ def test_opt_out_second_reminder(self, _): ) tasks.no_canteen_second_reminder() - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() marie.refresh_from_db() @@ -478,9 +478,9 @@ def test_opt_out_no_diagnostic_first_reminder(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Anna - tasks._send_sib_template.assert_called - self.assertEqual(tasks._send_sib_template.call_count, 1) - call_args_list = tasks._send_sib_template.call_args_list + tasks.send_sib_template.assert_called + self.assertEqual(tasks.send_sib_template.call_count, 1) + call_args_list = tasks.send_sib_template.call_args_list self.assertEqual(call_args_list[0][0][2], "anna.logue@example.com") # DB objects are updated @@ -526,7 +526,7 @@ def test_no_diagnostic_satellite(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Jean - tasks._send_sib_template.assert_not_called() + tasks.send_sib_template.assert_not_called() # DB objects remain unchanged canteen_no_diagnostics.refresh_from_db() From ba57656715514de509d50ccfcdc26a685cbe9170 Mon Sep 17 00:00:00 2001 From: Quentin Loridant Date: Mon, 28 Oct 2024 17:49:56 +0100 Subject: [PATCH 3/4] Change order to first create missing Brevo contacts --- macantine/tasks.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/macantine/tasks.py b/macantine/tasks.py index 348938267..ba2ba5357 100644 --- a/macantine/tasks.py +++ b/macantine/tasks.py @@ -135,19 +135,16 @@ def update_brevo_contacts(): today = timezone.now() threshold = today - datetime.timedelta(days=1) - # Attempt a bulk update first to save API calls - users_to_update = User.objects.filter(Q(last_brevo_update__lte=threshold) | Q(last_brevo_update__isnull=True)) + logger.info("Create individually new Brevo users (allowing the update flag to be set)") + users_to_update = User.objects.filter(Q(last_brevo_update__isnull=True)) + create_new_brevo_users(users_to_update, today) + + logger.info("Update existing Brevo contacts by batch") + users_to_update = User.objects.filter(Q(last_brevo_update__lte=threshold)) bulk_update_size = 100 chunks = batched(users_to_update, bulk_update_size) - - logger.info("update_brevo_contacts batch updating started") update_existing_brevo_contacts(chunks, today) - # Try creating those who didn't make it (allowing the update flag to be set) - users_to_update = User.objects.filter(Q(last_brevo_update__lte=threshold) | Q(last_brevo_update__isnull=True)) - logger.info("update_brevo_contacts individual creating/updating started") - create_new_brevo_users(chunks, today) - end = time.time() logger.info(f"update_brevo_contacts task ended. Duration : { end - start } seconds") From bd6a58c2834625f5013fcd848f70eb00fedc8e7c Mon Sep 17 00:00:00 2001 From: Quentin Loridant Date: Tue, 29 Oct 2024 15:39:55 +0100 Subject: [PATCH 4/4] Adapt tests to refacto --- macantine/tasks.py | 16 +++--- macantine/tests/test_automatic_emails.py | 62 ++++++++++++------------ macantine/tests/test_brevo_user_data.py | 28 +++++------ 3 files changed, 51 insertions(+), 55 deletions(-) diff --git a/macantine/tasks.py b/macantine/tasks.py index ba2ba5357..edf382b50 100644 --- a/macantine/tasks.py +++ b/macantine/tasks.py @@ -13,15 +13,11 @@ from django.utils import timezone from sib_api_v3_sdk.rest import ApiException +import macantine.brevo as brevo from api.views.utils import update_change_reason from common.utils import get_token_sirene from data.models import Canteen, User -from .brevo import ( - create_new_brevo_users, - send_sib_template, - update_existing_brevo_contacts, -) from .celery import app from .etl.analysis import ETL_ANALYSIS_CANTEEN, ETL_ANALYSIS_TD from .etl.open_data import ETL_OPEN_DATA_CANTEEN, ETL_OPEN_DATA_TD @@ -58,7 +54,7 @@ def no_canteen_first_reminder(): try: parameters = {"PRENOM": user.first_name} to_name = _user_name(user) - send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_FIRST, parameters, user.email, to_name) + brevo.send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_FIRST, parameters, user.email, to_name) logger.info(f"First email sent to {user.get_full_name()} ({user.email})") user.email_no_canteen_first_reminder = today user.save() @@ -93,7 +89,7 @@ def no_canteen_second_reminder(): try: parameters = {"PRENOM": user.first_name} to_name = _user_name(user) - send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_SECOND, parameters, user.email, to_name) + brevo.send_sib_template(settings.TEMPLATE_ID_NO_CANTEEN_SECOND, parameters, user.email, to_name) logger.info(f"Second email sent to {user.get_full_name()} ({user.email})") user.email_no_canteen_second_reminder = today user.save() @@ -137,13 +133,13 @@ def update_brevo_contacts(): logger.info("Create individually new Brevo users (allowing the update flag to be set)") users_to_update = User.objects.filter(Q(last_brevo_update__isnull=True)) - create_new_brevo_users(users_to_update, today) + brevo.create_new_brevo_users(users_to_update, today) logger.info("Update existing Brevo contacts by batch") users_to_update = User.objects.filter(Q(last_brevo_update__lte=threshold)) bulk_update_size = 100 chunks = batched(users_to_update, bulk_update_size) - update_existing_brevo_contacts(chunks, today) + brevo.update_existing_brevo_contacts(chunks, today) end = time.time() logger.info(f"update_brevo_contacts task ended. Duration : { end - start } seconds") @@ -175,7 +171,7 @@ def no_diagnostic_first_reminder(): try: parameters = {"PRENOM": manager.first_name, "NOM_CANTINE": canteen.name} to_name = _user_name(manager) - send_sib_template( + brevo.send_sib_template( settings.TEMPLATE_ID_NO_DIAGNOSTIC_FIRST, parameters, manager.email, diff --git a/macantine/tests/test_automatic_emails.py b/macantine/tests/test_automatic_emails.py index ae13c1d36..33edca6a9 100644 --- a/macantine/tests/test_automatic_emails.py +++ b/macantine/tests/test_automatic_emails.py @@ -7,11 +7,11 @@ from data.factories import CanteenFactory, DiagnosticFactory, UserFactory from data.models import Canteen -from macantine import tasks +from macantine import brevo, tasks class TestAutomaticEmails(TestCase): - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_canteen_first_reminder(self, _): @@ -59,7 +59,7 @@ def test_no_canteen_first_reminder(self, _): tasks.no_canteen_first_reminder() # Email is only sent once to Jean - tasks.send_sib_template.assert_called_once_with( + brevo.send_sib_template.assert_called_once_with( 1, {"PRENOM": "Jean"}, "jean.serien@example.com", "Jean Sérien" ) @@ -73,7 +73,7 @@ def test_no_canteen_first_reminder(self, _): self.assertIsNone(anna.email_no_canteen_first_reminder) self.assertIsNone(sophie.email_no_canteen_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_canteen_dev_profile(self, _): @@ -94,12 +94,12 @@ def test_no_canteen_dev_profile(self, _): ) tasks.no_canteen_first_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() jean.refresh_from_db() self.assertIsNone(jean.email_no_canteen_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_SECOND=2) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_canteen_second_reminder(self, _): @@ -161,7 +161,7 @@ def test_no_canteen_second_reminder(self, _): tasks.no_canteen_second_reminder() # Email is only sent once to Marie - tasks.send_sib_template.assert_called_once_with(2, {"PRENOM": ""}, "marie.olait@example.com", "marie.olait") + brevo.send_sib_template.assert_called_once_with(2, {"PRENOM": ""}, "marie.olait@example.com", "marie.olait") jean.refresh_from_db() anna.refresh_from_db() @@ -174,7 +174,7 @@ def test_no_canteen_second_reminder(self, _): self.assertIsNone(anna.email_no_canteen_second_reminder) self.assertIsNone(sophie.email_no_canteen_second_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_SECOND=2) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_canteen_second_reminder_dev(self, _): @@ -193,12 +193,12 @@ def test_no_canteen_second_reminder_dev(self, _): is_dev=True, ) tasks.no_canteen_second_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() marie.refresh_from_db() self.assertIsNone(marie.email_no_canteen_second_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=None) @override_settings(TEMPLATE_ID_NO_CANTEEN_SECOND=None) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) @@ -225,9 +225,9 @@ def test_no_template_settings(self, _): tasks.no_canteen_first_reminder() tasks.no_canteen_second_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=1) @override_settings(TEMPLATE_ID_NO_CANTEEN_SECOND=2) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) @@ -257,20 +257,20 @@ def test_emails_should_only_be_sent_once(self, _): tasks.no_canteen_first_reminder() tasks.no_canteen_first_reminder() tasks.no_canteen_first_reminder() - tasks.send_sib_template.assert_called_once_with( + brevo.send_sib_template.assert_called_once_with( 1, {"PRENOM": "Jean"}, "jean.serien@example.com", "Jean Sérien" ) - tasks.send_sib_template.reset_mock() + brevo.send_sib_template.reset_mock() tasks.no_canteen_second_reminder() tasks.no_canteen_second_reminder() tasks.no_canteen_second_reminder() - tasks.send_sib_template.assert_called_once_with( + brevo.send_sib_template.assert_called_once_with( 2, {"PRENOM": "Marie"}, "marie.olait@example.com", "Marie Olait" ) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_DIAGNOSTIC_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_diagnostic_first_reminder(self, _): @@ -356,9 +356,9 @@ def test_no_diagnostic_first_reminder(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Jean - tasks.send_sib_template.assert_called() - self.assertEqual(tasks.send_sib_template.call_count, 2) - call_args_list = tasks.send_sib_template.call_args_list + brevo.send_sib_template.assert_called() + self.assertEqual(brevo.send_sib_template.call_count, 2) + call_args_list = brevo.send_sib_template.call_args_list recipients = [x[0][2] for x in call_args_list] self.assertIn("jean.serien@example.com", recipients) self.assertIn("anna.logue@example.com", recipients) @@ -367,7 +367,7 @@ def test_no_diagnostic_first_reminder(self, _): canteen_no_diagnostics.refresh_from_db() self.assertIsNotNone(canteen_no_diagnostics.email_no_diagnostic_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_DIAGNOSTIC_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_diagnostic_dev_profile(self, _): @@ -388,12 +388,12 @@ def test_no_diagnostic_dev_profile(self, _): Canteen.objects.filter(pk=canteen_no_diagnostics.id).update(creation_date=(today - timedelta(weeks=2))) tasks.no_diagnostic_first_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() canteen_no_diagnostics.refresh_from_db() self.assertIsNone(canteen_no_diagnostics.email_no_diagnostic_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_email_opt_out_first_reminder(self, _): @@ -413,11 +413,11 @@ def test_email_opt_out_first_reminder(self, _): ) tasks.no_canteen_first_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() self.assertIsNone(jean.email_no_canteen_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_CANTEEN_SECOND=2) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_opt_out_second_reminder(self, _): @@ -438,13 +438,13 @@ def test_opt_out_second_reminder(self, _): ) tasks.no_canteen_second_reminder() - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() marie.refresh_from_db() self.assertIsNone(marie.email_no_canteen_second_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_DIAGNOSTIC_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_opt_out_no_diagnostic_first_reminder(self, _): @@ -478,16 +478,16 @@ def test_opt_out_no_diagnostic_first_reminder(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Anna - tasks.send_sib_template.assert_called - self.assertEqual(tasks.send_sib_template.call_count, 1) - call_args_list = tasks.send_sib_template.call_args_list + brevo.send_sib_template.assert_called + self.assertEqual(brevo.send_sib_template.call_count, 1) + call_args_list = brevo.send_sib_template.call_args_list self.assertEqual(call_args_list[0][0][2], "anna.logue@example.com") # DB objects are updated canteen_no_diagnostics.refresh_from_db() self.assertIsNotNone(canteen_no_diagnostics.email_no_diagnostic_first_reminder) - @mock.patch("macantine.tasks._send_sib_template") + @mock.patch("macantine.brevo.send_sib_template") @override_settings(TEMPLATE_ID_NO_DIAGNOSTIC_FIRST=1) @override_settings(ANYMAIL={"SENDINBLUE_API_KEY": "fake-api-key"}) def test_no_diagnostic_satellite(self, _): @@ -526,7 +526,7 @@ def test_no_diagnostic_satellite(self, _): tasks.no_diagnostic_first_reminder() # Email is only sent once to Jean - tasks.send_sib_template.assert_not_called() + brevo.send_sib_template.assert_not_called() # DB objects remain unchanged canteen_no_diagnostics.refresh_from_db() diff --git a/macantine/tests/test_brevo_user_data.py b/macantine/tests/test_brevo_user_data.py index 073688da0..7cae7cec9 100644 --- a/macantine/tests/test_brevo_user_data.py +++ b/macantine/tests/test_brevo_user_data.py @@ -48,8 +48,8 @@ def test_batch_user_updates(self, batch_update_mock, create_contact_mock): self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), False) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), False) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_create_user(self, batch_update_mock, create_contact_mock): """ If the batch update fails then the user will be created/updated individually @@ -64,8 +64,8 @@ def test_create_user(self, batch_update_mock, create_contact_mock): payload = create_contact_mock.call_args[0][0] self.assertEqual(payload.email, new_user.email) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_empty_canteen(self, batch_update_mock, create_contact_mock): """ As soon as a user has a canteen, pending actions will follow and all paramteres @@ -90,8 +90,8 @@ def test_user_has_empty_canteen(self, batch_update_mock, create_contact_mock): self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), True) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), True) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_published_canteen(self, batch_update_mock, create_contact_mock): user = UserFactory.create() canteen = CanteenFactory.create(publication_status=Canteen.PublicationStatus.PUBLISHED) @@ -112,8 +112,8 @@ def test_user_has_published_canteen(self, batch_update_mock, create_contact_mock self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), True) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), False) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_canteen_with_diag(self, batch_update_mock, create_contact_mock): user = UserFactory.create() canteen = CanteenFactory.create() @@ -137,8 +137,8 @@ def test_user_has_canteen_with_diag(self, batch_update_mock, create_contact_mock self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), True) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), True) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_canteen_with_td(self, batch_update_mock, create_contact_mock): user = UserFactory.create() canteen = CanteenFactory.create() @@ -177,8 +177,8 @@ def test_user_has_canteen_with_td(self, batch_update_mock, create_contact_mock): self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), False) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), True) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_sat_canteen_with_cc_diag(self, batch_update_mock, create_contact_mock): user = UserFactory.create() central_kitchen = CanteenFactory.create(production_type=Canteen.ProductionType.CENTRAL, siret="65815950319874") @@ -213,8 +213,8 @@ def test_user_has_sat_canteen_with_cc_diag(self, batch_update_mock, create_conta self.assertEqual(attributes.get("MA_CANTINE_MANQUE_TD_DONNEES_2021"), True) self.assertEqual(attributes.get("MA_CANTINE_MANQUE_PUBLICATION"), True) - @mock.patch("macantine.tasks.contacts_api_instance.create_contact") - @mock.patch("macantine.tasks.contacts_api_instance.update_batch_contacts") + @mock.patch("macantine.brevo.contacts_api_instance.create_contact") + @mock.patch("macantine.brevo.contacts_api_instance.update_batch_contacts") def test_user_has_sat_canteen_with_cc_td(self, batch_update_mock, create_contact_mock): user = UserFactory.create() central_kitchen = CanteenFactory.create(production_type=Canteen.ProductionType.CENTRAL, siret="65815950319874")