Skip to content

Commit

Permalink
Ajouter le code de base pour les notifications
Browse files Browse the repository at this point in the history
Ajout de Django Post office pour la gestion des files d'attentes des
mails.
Ajout de la logique métier en fonction de chaque type de message.
  • Loading branch information
Anto59290 committed Sep 18, 2024
1 parent 7257825 commit d649a42
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 8 deletions.
2 changes: 2 additions & 0 deletions core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MUS_STRUCTURE = "MUS"
BSV_STRUCTURE = "SAS/SDSPV/BSV"
12 changes: 10 additions & 2 deletions core/managers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.contrib.contenttypes.models import ContentType
from django.db.models import Case, When, Value, IntegerField, QuerySet

from core.constants import MUS_STRUCTURE, BSV_STRUCTURE


class DocumentQueryset(QuerySet):
def order_list(self):
Expand Down Expand Up @@ -28,7 +30,13 @@ def with_structure_and_agent(self):
return self.select_related("structure", "agent")

def get_mus(self):
return self.get(structure__niveau2="MUS")
return self.get(structure__niveau2=MUS_STRUCTURE)

def get_bsv(self):
return self.get(structure__niveau2="SAS/SDSPV/BSV")
return self.get(structure__niveau2=BSV_STRUCTURE)

def has_agent(self):
return self.exclude(agent__isnull=True)

def has_structure(self):
return self.exclude(structure__isnull=True)
2 changes: 1 addition & 1 deletion core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ class Message(models.Model):
)
TYPES_TO_FEMINIZE = (NOTE, DEMANDE_INTERVENTION, FIN_SUIVI)
TYPES_WITHOUT_RECIPIENTS = (NOTE, POINT_DE_SITUATION, FIN_SUIVI)
TYPES_WITH_LIMITED_RECIPIENTS = COMPTE_RENDU
TYPES_WITH_LIMITED_RECIPIENTS = (COMPTE_RENDU,)

message_type = models.CharField(max_length=100, choices=MESSAGE_TYPE_CHOICES)
title = models.CharField(max_length=512, verbose_name="Titre")
Expand Down
45 changes: 45 additions & 0 deletions core/notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from post_office import mail

from core.constants import MUS_STRUCTURE
from core.models import Message


def _send_message(recipients: list[str], copy: list[str], subject, message):
mail.send(
recipients=recipients,
cc=copy,
sender="[email protected]",
subject=f"SEVES - {subject}",
message=message,
)


def notify_message(instance: Message):
recipients, copy = [], []
message, subject = None, None
if instance.message_type == Message.MESSAGE:
subject = instance.title
message = f"Bonjour,\n Vous avez reçu un message sur SEVES dont voici le contenu : \n {instance.content}"
recipients = [r.email for r in instance.recipients.all()]
copy = [r.email for r in instance.recipients_copy.all()]
elif instance.message_type == Message.COMPTE_RENDU:
subject = instance.title
message = f"Bonjour,\n Vous avez reçu un compte rendu sur demande d'intervention sur SEVES dont voici le contenu : \n {instance.content}"
recipients = [r.email for r in instance.recipients.all()]
elif instance.message_type == Message.DEMANDE_INTERVENTION:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un message sur SEVES."
recipients = [r.email for r in instance.recipients.has_structure()]
copy = [r.email for r in instance.recipients_copy.has_structure()]
elif instance.message_type == Message.POINT_DE_SITUATION:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
recipients = [c.email for c in instance.content_object.contacts.has_agent()]
elif instance.message_type == Message.FIN_SUIVI:
subject = instance.title
message = "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
recipients = instance.content_object.contacts.has_agent().filter(agent__structure__niveau2=MUS_STRUCTURE)
recipients = [r.email for r in recipients]

if recipients and message:
_send_message(recipients, copy, subject=subject, message=message)
3 changes: 2 additions & 1 deletion core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
)
from django.http import HttpResponseRedirect
from django.utils.translation import ngettext

from .notifications import notify_message

from .models import Document, Message, Contact, FinSuiviContact

Expand Down Expand Up @@ -235,6 +235,7 @@ def form_valid(self, form):
response = super().form_valid(form)
self._add_contacts_to_object(form.instance)
self._create_documents(form)
notify_message(form.instance)
messages.success(self.request, "Le message a bien été ajouté.", extra_tags="core messages")
return response

Expand Down
4 changes: 3 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ env =
OIDC_RP_USER_ENDPOINT=
OIDC_RP_JWKS_ENDPOINT=
OIDC_RP_LOGOUT_ENDPOINT=
CACHE_CLASS=django.core.cache.backends.dummy.DummyCache
CACHE_CLASS=django.core.cache.backends.dummy.DummyCache
EMAIL_BACKEND=django.core.mail.backends.locmem.EmailBackend
EMAIL_PRIORITY=now
3 changes: 2 additions & 1 deletion requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ django-storages[s3]
mozilla-django-oidc
django-filter
faker
django-debug-toolbar
django-debug-toolbar
django-post_office
17 changes: 15 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile
# pip-compile requirements.in
#
asgiref==3.7.2
# via django
bleach[css]==6.1.0
# via django-post-office
boto3==1.34.134
# via django-storages
botocore==1.34.134
Expand Down Expand Up @@ -36,6 +38,7 @@ django==5.0.3
# -r requirements.in
# django-debug-toolbar
# django-filter
# django-post-office
# django-storages
# model-bakery
# mozilla-django-oidc
Expand All @@ -46,6 +49,8 @@ django-environ==0.11.2
# via -r requirements.in
django-filter==24.2
# via -r requirements.in
django-post-office==3.9.0
# via -r requirements.in
django-storages[s3]==1.14.3
# via -r requirements.in
djhtml==3.0.6
Expand Down Expand Up @@ -136,7 +141,9 @@ s3transfer==0.10.2
sentry-sdk[django]==2.5.1
# via -r requirements.in
six==1.16.0
# via python-dateutil
# via
# bleach
# python-dateutil
sqlparse==0.4.4
# via
# django
Expand All @@ -145,6 +152,8 @@ static3==0.7.0
# via dj-static
text-unidecode==1.3
# via python-slugify
tinycss2==1.2.1
# via bleach
typing-extensions==4.11.0
# via pyee
urllib3==2.2.1
Expand All @@ -154,6 +163,10 @@ urllib3==2.2.1
# sentry-sdk
virtualenv==20.25.3
# via pre-commit
webencodings==0.5.1
# via
# bleach
# tinycss2

# The following packages are considered to be unsafe in a requirements file:
# setuptools
8 changes: 8 additions & 0 deletions seves/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"sv.apps.SvConfig",
"core.apps.CoreConfig",
"django_filters",
"post_office",
]

MIDDLEWARE = [
Expand Down Expand Up @@ -204,3 +205,10 @@
INSTALLED_APPS.append("debug_toolbar")
MIDDLEWARE.insert(0, "debug_toolbar.middleware.DebugToolbarMiddleware")
INTERNAL_IPS = ["127.0.0.1"]

POST_OFFICE = {
"BACKENDS": {
"default": env("EMAIL_BACKEND", default="django.core.mail.backends.console.EmailBackend"),
},
"DEFAULT_PRIORITY": env("EMAIL_PRIORITY", default="medium"),
}
124 changes: 124 additions & 0 deletions sv/tests/test_notifications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import pytest
from model_bakery import baker

from core.models import Structure, Agent, Contact, Message
from core.notifications import notify_message


@pytest.mark.django_db
def test_notification_message(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
contact_1 = baker.make(Contact, agent=baker.make(Agent))
contact_2 = baker.make(Contact, structure=baker.make(Structure))
contact_3 = baker.make(Contact, structure=baker.make(Structure))
contact_4 = baker.make(Contact, agent=baker.make(Agent))
_contact_5 = baker.make(Contact, structure=baker.make(Structure))
_contact_6 = baker.make(Contact, agent=baker.make(Agent))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.MESSAGE,
content_object=fiche_detection,
)
message.recipients.set([contact_1, contact_2])
message.recipients_copy.set([contact_3, contact_4])

notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert (
message.body == "Bonjour,\n Vous avez reçu un message sur SEVES dont voici le contenu : \n My message \n Thanks"
)
assert message.from_email == "[email protected]"
assert set(message.to) == {contact_1.email, contact_2.email}
assert set(message.cc) == {contact_3.email, contact_4.email}


@pytest.mark.django_db
def test_notification_demande_intervention(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
agent_1 = baker.make(Contact, agent=baker.make(Agent))
agent_2 = baker.make(Contact, agent=baker.make(Agent))
_agent_3 = baker.make(Contact, agent=baker.make(Agent))
structure_1 = baker.make(Contact, structure=baker.make(Structure))
structure_2 = baker.make(Contact, structure=baker.make(Structure))
_structure_3 = baker.make(Contact, structure=baker.make(Structure))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.DEMANDE_INTERVENTION,
content_object=fiche_detection,
)
message.recipients.set([agent_1, structure_1])
message.recipients_copy.set([agent_2, structure_2])

notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert message.body == "Bonjour,\n Vous avez reçu un message sur SEVES."
assert message.from_email == "[email protected]"
assert set(message.to) == {structure_1.email}
assert set(message.cc) == {structure_2.email}


@pytest.mark.django_db
def test_notification_point_de_situation(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
agent_1 = baker.make(Contact, agent=baker.make(Agent))
_agent_2 = baker.make(Contact, agent=baker.make(Agent))
structure_1 = baker.make(Contact, structure=baker.make(Structure))
_structure_2 = baker.make(Contact, structure=baker.make(Structure))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.POINT_DE_SITUATION,
content_object=fiche_detection,
)
fiche_detection.contacts.set([agent_1, structure_1])

notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert message.body == "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
assert message.from_email == "[email protected]"
assert set(message.to) == {agent_1.email}
assert set(message.cc) == set()


@pytest.mark.django_db
def test_notification_fin_de_suivi(mailoutbox, fiche_detection):
sender = baker.make(Contact, agent=baker.make(Agent))
agent_1 = baker.make(Contact, agent=baker.make(Agent, structure__niveau2="MUS"))
agent_2 = baker.make(Contact, agent=baker.make(Agent, structure__niveau2="FOO"))
structure_1 = baker.make(Contact, structure=baker.make(Structure))

message = Message.objects.create(
title="TITLE",
content="My message \n Thanks",
sender=sender,
message_type=Message.FIN_SUIVI,
content_object=fiche_detection,
)
fiche_detection.contacts.set([agent_1, agent_2, structure_1])

notify_message(message)

assert len(mailoutbox) == 1
message = mailoutbox[0]
assert message.subject == "SEVES - TITLE"
assert message.body == "Bonjour,\n Vous avez reçu un nouveau point de suivi sur SEVES."
assert message.from_email == "[email protected]"
assert set(message.to) == {agent_1.email}
assert set(message.cc) == set()

0 comments on commit d649a42

Please sign in to comment.