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: simplifier la collecte des destinataires des questions en attente #833

Merged
merged 6 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
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
6 changes: 1 addition & 5 deletions clevercloud/cron.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,5 @@
"*/15 7-21 * * * $ROOT/clevercloud/send_notifications_regular.sh",
"20 6 * * * $ROOT/clevercloud/send_notifications_daily.sh",
"10 6-22 * * * $ROOT/clevercloud/add_user_to_list_when_register.sh",
"30 13 * * 1 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh 8",
"30 13 * * 2 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh 9",
"30 13 * * 3 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh 10",
"30 13 * * 4 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh 11",
"30 13 * * 5 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh 12"
"30 13 * * 1-5 $ROOT/clevercloud/send_notifs_on_unanswered_topics_list.sh"
]
6 changes: 1 addition & 5 deletions clevercloud/send_notifs_on_unanswered_topics_list.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#!/bin/bash -l

if [ -z "$1" ]; then
echo "Error: Missing argument. Please provide List ID."
exit 1
fi

#
# About clever cloud cronjobs:
Expand All @@ -18,4 +14,4 @@ fi
# $APP_HOME is set by default by clever cloud.
cd $APP_HOME

python manage.py send_notifs_on_unanswered_topics --list_id $1
python manage.py send_notifs_on_unanswered_topics
1 change: 0 additions & 1 deletion config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@
SIB_URL = os.getenv("SIB_URL", "http://test.com")
SIB_SMTP_URL = os.path.join(SIB_URL, "smtp/email")
SIB_CONTACTS_URL = os.path.join(SIB_URL, "contacts/import")
SIB_CONTACT_LIST_URL = os.path.join(SIB_URL, "contacts/lists")

SIB_API_KEY = os.getenv("SIB_API_KEY", "set-sib-api-key")
DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL", "[email protected]")
Expand Down
151 changes: 3 additions & 148 deletions lacommunaute/forum_conversation/tests/__snapshots__/tests_views.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


<a class="matomo-event" data-matomo-action="view" data-matomo-category="engagement" data-matomo-option="member" href="/members/profile/poster_username/">
Alan T.
Adam O.
</a>,


Expand All @@ -23,7 +23,7 @@


<a class="matomo-event" data-matomo-action="view" data-matomo-category="engagement" data-matomo-option="member" href="/members/profile/poster_username/">
Dermot T.
Adam O.
</a>,
il y a 0 minute

Expand All @@ -37,158 +37,13 @@


<a class="matomo-event" data-matomo-action="view" data-matomo-category="engagement" data-matomo-option="member" href="/members/profile/poster_username/">
Jeff B.
Adam O.
</a>,
il y a 0 minute

</small>
'''
# ---
# name: TestTopicCreateCheckView.test_get_method[topic_create_check]
'''
<main class="s-main" id="main" role="main">





<section class="s-section" id="main_container">
<div class="s-section__container container">

<div class="row">
<div class="col-12">
<h1>forum</h1>
</div>
</div>
<div class="row c-box">
<div class="col-12 mb-5">
<p class="h2">Quelle est ma situation ?</p>
</div>
<div class="col-12 col-md-4 mb-3">
<div class="card c-card h-100">
<div class="card-header">
<h3 class="h4">J'utilise le site des emplois de l'inclusion</h3>
</div>
<div class="card-body pb-0">
<p>
J'ai des questions sur les PASS IAE, leur suspension ou prolongation, le fonctionnement du site des emplois de l'inclusion ou les relations avec l'ASP
</p>
</div>
<div class="card-footer text-center mt-3">
<a class="btn btn-primary matomo-event" data-matomo-action="topic-create-check" data-matomo-category="engagement" data-matomo-option="itou-helpdesk" href="https://aide.emplois.inclusion.beta.gouv.fr/hc/fr">J'accède à la documentation des emplois de l'inclusion</a>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-3">
<div class="card c-card h-100">
<div class="card-header">
<h3 class="h4">J'accueille des personnes en PMSMP</h3>
</div>
<div class="card-body pb-0">
<p>
J'ai une question Période de Mise en Situation en Milieu Professionnel, le conventionnement, la déclaration des heures ou le fonctionnement du site Immersion Facilitée
</p>
</div>
<div class="card-footer text-center">
<a class="btn btn-primary matomo-event" data-matomo-action="topic-create-check" data-matomo-category="engagement" data-matomo-option="pmsmp" href="https://aide.immersion-facile.beta.gouv.fr/fr/">
J'accède au centre d'aide Immersion Facilitée
</a>
</div>
</div>
</div>
<div class="col-12 col-md-4 mb-3">
<div class="card c-card h-100">
<div class="card-header">
<h3 class="h4">Je suis un/une professionnel/le de l'insertion, en formation ou en activité</h3>
</div>
<div class="card-body pb-0">
<p>
J'ai une question sur l'accompagnement d'une personne éloignée de l'emploi, sur mon parcours de formation ou sur une des fiches pratiques de la communauté
</p>
</div>
<div class="card-footer text-center">
<a class="btn btn-primary matomo-event" data-matomo-action="topic-create-check" data-matomo-category="engagement" data-matomo-option="forum" href="/forum/forum-[PK of Forum]/topic/create/?checked">Je pose ma question à la communauté</a>
</div>
</div>
</div>
</div>

</div>
</section>

</main>
'''
# ---
# name: TestTopicCreateView.test_redirections_on_documentation_forum[topic_create]
'''
<div class="form-group" id="div_id_content">


<label class="control-label" for="id_content">
Message

</label>


<textarea class="form-control" cols="40" id="id_content" name="content" placeholder="Entrez votre message" required="" rows="10"></textarea>






<small class="form-text text-muted">
<a aria-controls="collapseMentionsHelp" aria-expanded="false" data-bs-toggle="collapse" href="#collapseMentionsHelp" role="button">mention d'informations</a>
sur les champs libres
</small>
<div class="collapse" id="collapseMentionsHelp">
<div class="mb-3">
<p>
Nous vous demandons de ne pas nous transmettre d’informations sensibles. Notamment, ne communiquez pas vos opinions philosophiques, syndicales, politiques ou sur votre vie sexuelle. Ces données sont trop personnelles !
</p>
</div>
</div>



</div>
'''
# ---
# name: TestTopicCreateView.test_redirections_on_forum[topic_create]
'''
<div class="form-group" id="div_id_content">


<label class="control-label" for="id_content">
Message

</label>


<textarea class="form-control" cols="40" id="id_content" name="content" placeholder="Entrez votre message" required="" rows="10"></textarea>






<small class="form-text text-muted">
<a aria-controls="collapseMentionsHelp" aria-expanded="false" data-bs-toggle="collapse" href="#collapseMentionsHelp" role="button">mention d'informations</a>
sur les champs libres
</small>
<div class="collapse" id="collapseMentionsHelp">
<div class="mb-3">
<p>
Nous vous demandons de ne pas nous transmettre d’informations sensibles. Notamment, ne communiquez pas vos opinions philosophiques, syndicales, politiques ou sur votre vie sexuelle. Ces données sont trop personnelles !
</p>
</div>
</div>



</div>
'''
# ---
# name: TestTopicListView.test_clickable_tags[10-query_param1-clickable_tags_page2][clickable_tags_page2]
'<button class="tag bg-info-lighter text-info matomo-event" data-matomo-action="filter" data-matomo-category="engagement" data-matomo-option="topics" hx-get="/topics/?tag=tag&amp;filter=ALL" hx-push-url="true" hx-swap="outerHTML" hx-target="#topicsarea" id="filtertopics-button">tag</button>'
# ---
Expand Down
6 changes: 3 additions & 3 deletions lacommunaute/forum_conversation/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ def test_filter_dropdown_with_tags(self, client, db, public_forum_with_topic, to

class TestPosterTemplate:
def test_topic_in_topics_view(self, client, db, topics_url, snapshot):
topic = TopicFactory(with_post=True, poster=UserFactory(first_name="Jeff", last_name="Buckley"))
topic = TopicFactory(with_post=True, poster=UserFactory(for_snapshot=True))
response = client.get(topics_url)
soup = parse_response_to_soup(
response, replace_in_href=[(topic.poster.username, "poster_username")], selector=".poster-infos"
Expand All @@ -990,7 +990,7 @@ def test_topic_from_other_public_forum_in_topics_view(self, client, db, topics_u
topic = TopicFactory(
with_post=True,
forum=ForumFactory(with_public_perms=True, name="Abby's Forum"),
poster=UserFactory(first_name="Alan", last_name="Turing"),
poster=UserFactory(for_snapshot=True),
)
response = client.get(topics_url)
soup = parse_response_to_soup(
Expand All @@ -1013,7 +1013,7 @@ def test_topic_in_its_own_public_forum(self, client, db, snapshot):
topic = TopicFactory(
with_post=True,
forum=ForumFactory(with_public_perms=True, name="Joe's Forum"),
poster=UserFactory(first_name="Dermot", last_name="Turing"),
poster=UserFactory(for_snapshot=True),
)
response = client.get(
reverse("forum_extension:forum", kwargs={"slug": topic.forum.slug, "pk": topic.forum.pk})
Expand Down
12 changes: 0 additions & 12 deletions lacommunaute/notification/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,3 @@ def bulk_send_user_to_list(users, list_id):
EmailSentTrack.objects.create(
status_code=response.status_code, response=response.text, datas=payload, kind=EmailSentTrackKind.ONBOARDING
)


def collect_users_from_list(list_id: int) -> list | None:
headers = {"api-key": settings.SIB_API_KEY, "Content-Type": "application/json", "Accept": "application/json"}
response = httpx.get(f"{settings.SIB_CONTACT_LIST_URL}/{list_id}/contacts", headers=headers)
if response.status_code == 200:
return [
{"email": contact["email"], "name": f'{contact["attributes"]["PRENOM"]} {contact["attributes"]["NOM"]}'}
for contact in response.json()["contacts"]
if not contact["emailBlacklisted"]
]
return None
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
class Command(BaseCommand):
help = "Envoyer une notification par email aux utilisateurs volontaires quand il y a des sujets sans réponse"

def add_arguments(self, parser):
parser.add_argument("--list_id", type=int, help="ID de la liste à utiliser")

def handle(self, *args, **options):
if "list_id" in options:
send_notifs_on_unanswered_topics(options["list_id"])
send_notifs_on_unanswered_topics()
self.stdout.write(self.style.SUCCESS("That's all, folks!"))
39 changes: 21 additions & 18 deletions lacommunaute/notification/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

from config.settings.base import DEFAULT_FROM_EMAIL, NEW_MESSAGES_EMAIL_MAX_PREVIEW, SIB_NEW_MESSAGES_TEMPLATE
from lacommunaute.forum_conversation.models import Topic
from lacommunaute.notification.emails import bulk_send_user_to_list, collect_users_from_list, send_email
from lacommunaute.forum_member.shortcuts import get_forum_member_display_name
from lacommunaute.notification.emails import bulk_send_user_to_list, send_email
from lacommunaute.notification.enums import EmailSentTrackKind, NotificationDelay
from lacommunaute.notification.models import Notification
from lacommunaute.notification.utils import collect_new_users_for_onboarding, get_serialized_messages
from lacommunaute.users.models import User


def send_messages_notifications(delay: NotificationDelay):
Expand Down Expand Up @@ -49,23 +51,24 @@ def add_user_to_list_when_register():
bulk_send_user_to_list(new_users, settings.SIB_ONBOARDING_LIST)


def send_notifs_on_unanswered_topics(list_id: int) -> None:
contacts = collect_users_from_list(list_id)
def send_notifs_on_unanswered_topics() -> None:
contacts = User.objects.filter(is_staff=True)
count = Topic.objects.unanswered().count()

if contacts:
count = Topic.objects.unanswered().count()
link = (
f"{settings.COMMU_PROTOCOL}://{settings.COMMU_FQDN}",
reverse("forum_conversation_extension:topics"),
"?filter=NEW&mtm_campaign=unsanswered&mtm_medium=email#community",
)
if not contacts.exists() or count == 0:
return None

params = {"count": count, "link": "".join(link)}
contacts_list = [{"email": contact.email, "name": get_forum_member_display_name(contact)} for contact in contacts]
link = (
f"{settings.COMMU_PROTOCOL}://{settings.COMMU_FQDN}",
reverse("forum_conversation_extension:topics"),
"?filter=NEW&mtm_campaign=unsanswered&mtm_medium=email#community",
)
params = {"count": count, "link": "".join(link)}

if count > 0:
send_email(
to=contacts,
params=params,
template_id=settings.SIB_UNANSWERED_QUESTION_TEMPLATE,
kind=EmailSentTrackKind.PENDING_TOPIC,
)
send_email(
to=contacts_list,
params=params,
template_id=settings.SIB_UNANSWERED_QUESTION_TEMPLATE,
kind=EmailSentTrackKind.PENDING_TOPIC,
)
46 changes: 2 additions & 44 deletions lacommunaute/notification/tests/tests_emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from django.test import TestCase
from faker import Faker

from config.settings.base import DEFAULT_FROM_EMAIL, SIB_CONTACT_LIST_URL, SIB_CONTACTS_URL, SIB_SMTP_URL
from lacommunaute.notification.emails import bulk_send_user_to_list, collect_users_from_list, send_email
from config.settings.base import DEFAULT_FROM_EMAIL, SIB_CONTACTS_URL, SIB_SMTP_URL
from lacommunaute.notification.emails import bulk_send_user_to_list, send_email
from lacommunaute.notification.models import EmailSentTrack
from lacommunaute.users.factories import UserFactory

Expand Down Expand Up @@ -79,45 +79,3 @@ def test_bulk_send_user_to_list(self):
self.assertEqual(email_sent_track.response, json.dumps({"message": "OK"}))
self.assertEqual(email_sent_track.datas, payload)
self.assertEqual(email_sent_track.kind, "onboarding")


class CollectUsersFromListTestCase(TestCase):
@classmethod
def setUpTestData(cls):
cls.contact_list_response = {
"contacts": [
{
"email": faker.email(),
"emailBlacklisted": False,
"attributes": {"PRENOM": faker.first_name(), "NOM": faker.name()},
},
{
"email": faker.email(),
"emailBlacklisted": True,
"attributes": {"PRENOM": faker.first_name(), "NOM": faker.name()},
},
]
}
respx.get(SIB_CONTACT_LIST_URL + "/1/contacts").mock(
return_value=httpx.Response(200, json=cls.contact_list_response)
)

@respx.mock
def test_collect_users_from_list_bad_status_code(self):
list_id = faker.random_int()
respx.get(SIB_CONTACT_LIST_URL + f"/{list_id}/contacts").mock(return_value=httpx.Response(500))
self.assertIsNone(collect_users_from_list(list_id))

@respx.mock
def test_collect_users_from_list(self):
expected_contact = self.contact_list_response["contacts"][0]
contacts = collect_users_from_list(1)
self.assertEqual(
contacts,
[
{
"email": expected_contact["email"],
"name": f'{expected_contact["attributes"]["PRENOM"]} {expected_contact["attributes"]["NOM"]}',
}
],
)
Loading