Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Email Notifications): Mise à jour côté Brevo du choix pour les communications Marketing #1639

Merged
merged 4 commits into from
Jan 23, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lemarche/conversations/models.py
Original file line number Diff line number Diff line change
@@ -195,6 +195,8 @@ def set_validated(self):


class EmailGroup(models.Model):
COMMUNICATION_MARKETING = "Communication marketing"

display_name = models.CharField(verbose_name="Nom", max_length=255, blank=True)
description = models.TextField(verbose_name="Description", blank=True)
relevant_user_kind = models.CharField(
12 changes: 12 additions & 0 deletions lemarche/utils/apis/api_brevo.py
Original file line number Diff line number Diff line change
@@ -99,6 +99,18 @@ def update_contact(user_identifier: str, attributes_to_update: dict):
logger.error(f"Exception when calling Brevo->ContactsApi->update_contact: {e}")


def update_contact_email_blacklisted(user_identifier: str, email_blacklisted: bool):
api_client = get_api_client()
api_instance = sib_api_v3_sdk.ContactsApi(api_client)

update_contact = sib_api_v3_sdk.UpdateContact(email_blacklisted=email_blacklisted)
try:
api_response = api_instance.update_contact(identifier=user_identifier, update_contact=update_contact)
logger.info(f"Success Brevo->ContactsApi->update_contact to update email_blacklisted: {api_response}")
except ApiException as e:
logger.error(f"Exception when calling Brevo->ContactsApi->update_contact to update email_blacklisted: {e}")


def remove_contact_from_list(user, list_id: int):
api_client = get_api_client()
api_instance = sib_api_v3_sdk.ContactsApi(api_client)
4 changes: 4 additions & 0 deletions lemarche/utils/emails.py
Original file line number Diff line number Diff line change
@@ -91,6 +91,10 @@ def add_to_contact_list(user, type: str, tender=None, source: str = user_constan
api_mailjet.add_to_contact_list_async(user.email, properties, contact_list_id)


def update_contact_email_blacklisted(email, email_blacklisted: bool):
api_brevo.update_contact_email_blacklisted(email, email_blacklisted)


@task()
def send_mail_async(
email_subject,
18 changes: 13 additions & 5 deletions lemarche/www/dashboard/forms.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
from lemarche.conversations.models import DisabledEmail, EmailGroup
from lemarche.sectors.models import Sector
from lemarche.users.models import User
from lemarche.utils.emails import update_contact_email_blacklisted
from lemarche.utils.fields import GroupedModelMultipleChoiceField
from lemarche.utils.widgets import CustomSelectMultiple

@@ -55,14 +56,21 @@ def __init__(self, *args, **kwargs):
def save(self):
disabled_emails = []

disabled_emails_marketing = False

# add unchecked fields to disabled_emails
for field_name, value in self.cleaned_data.items():
if field_name.startswith("email_group_"):
if not value:
group = EmailGroup.objects.get(pk=int(field_name.replace("email_group_", "")))
disabled_email, _ = DisabledEmail.objects.get_or_create(user=self.user, group=group)
disabled_emails.append(disabled_email)
if field_name.startswith("email_group_") and not value:
group = EmailGroup.objects.get(pk=int(field_name.replace("email_group_", "")))
disabled_email, _ = DisabledEmail.objects.get_or_create(user=self.user, group=group)
disabled_emails.append(disabled_email)

if group.display_name == EmailGroup.COMMUNICATION_MARKETING:
disabled_emails_marketing = True

self.user.disabled_emails.set(disabled_emails)

# remove old disabled_emails
DisabledEmail.objects.exclude(pk__in=[de.pk for de in disabled_emails]).delete()

update_contact_email_blacklisted(self.user.email, disabled_emails_marketing)
53 changes: 49 additions & 4 deletions lemarche/www/dashboard/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from unittest.mock import patch

from django.test import TestCase
from django.urls import reverse

@@ -71,6 +73,12 @@ class DisabledEmailEditViewTest(TestCase):
def setUp(self):
self.user = UserFactory(kind=User.KIND_BUYER)
self.url = reverse("dashboard:notifications_edit")
self.email_group_1 = EmailGroup.objects.get(
relevant_user_kind=User.KIND_BUYER, display_name="Structure(s) intéressée(s)"
)
self.email_group_2 = EmailGroup.objects.get(
relevant_user_kind=User.KIND_BUYER, display_name="Communication marketing"
)

def test_login_required(self):
response = self.client.get(self.url)
@@ -88,18 +96,55 @@ def test_get_form_displays_correctly(self):
self.assertContains(response, group.display_name)
self.assertContains(response, " checked>", count=2)

def test_form_submission_updates_preferences(self):
@patch("lemarche.utils.apis.api_brevo.sib_api_v3_sdk.ContactsApi")
def test_form_submission_updates_preferences_with_marketing_disabled(self, mock_contacts_api):
# Setup the mock
mock_api_instance = mock_contacts_api.return_value

self.assertEqual(self.user.disabled_emails.count(), 0)
self.client.force_login(self.user)
response = self.client.post(
self.url,
{
"email_group_1": True,
"email_group_2": False,
f"email_group_{self.email_group_1.pk}": True,
f"email_group_{self.email_group_2.pk}": False,
},
follow=True,
)

# Verify the API was called correctly
mock_api_instance.update_contact.assert_called_once()
call_args = mock_api_instance.update_contact.call_args
self.assertEqual(call_args[1]["identifier"], self.user.email)
self.assertEqual(call_args[1]["update_contact"].email_blacklisted, True)

self.assertContains(response, "Vos préférences de notifications ont été mises à jour.")
self.user.refresh_from_db()
self.assertEqual(self.user.disabled_emails.count(), 1)
self.assertEqual(self.user.disabled_emails.first().group.pk, 2)
self.assertIsNotNone(self.user.disabled_emails.get(group=self.email_group_2))

@patch("lemarche.utils.apis.api_brevo.sib_api_v3_sdk.ContactsApi")
def test_form_submission_updates_preferences_with_marketing_enabled(self, mock_contacts_api):
# Setup the mock
mock_api_instance = mock_contacts_api.return_value

self.assertEqual(self.user.disabled_emails.count(), 0)
self.client.force_login(self.user)
response = self.client.post(
self.url,
{
f"email_group_{self.email_group_1.pk}": True,
f"email_group_{self.email_group_2.pk}": True,
},
follow=True,
)

# Verify the API was called correctly
mock_api_instance.update_contact.assert_called_once()
call_args = mock_api_instance.update_contact.call_args
self.assertEqual(call_args[1]["identifier"], self.user.email)
self.assertEqual(call_args[1]["update_contact"].email_blacklisted, False)

self.assertContains(response, "Vos préférences de notifications ont été mises à jour.")
self.user.refresh_from_db()
self.assertEqual(self.user.disabled_emails.count(), 0)