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

Accusé de réception après l'ajout d'un fichier #434

Merged
merged 7 commits into from
Oct 7, 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: 5 additions & 1 deletion cron.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
"size": "M"
},
{
"command": "10 * * * * python manage.py new_files_alert",
"command": "10 * * * * python manage.py new_files_admin_alert",
"size": "M"
},
{
"command": "*/15 * * * * python manage.py new_files_user_alert",
"size": "M"
}
]
Expand Down
59 changes: 59 additions & 0 deletions envergo/evaluations/management/commands/new_files_user_alert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from datetime import timedelta
from itertools import groupby

from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.core.management.base import BaseCommand
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.timezone import localtime

from envergo.evaluations.models import RequestFile
from envergo.utils.tools import get_base_url


class Command(BaseCommand):
help = "Post a message when a an evalreq has a new file."

def handle(self, *args, **options):

base_url = get_base_url(settings.ENVERGO_AMENAGEMENT_DOMAIN)

# We want to notify users when they uploaded a new file.
# Wait 15 minutes after the last uploaded file to send a notification.
a_quarter_hr_ago = localtime() - timedelta(minutes=15)
half_hour_ago = localtime() - timedelta(minutes=30)

files = (
RequestFile.objects.filter(uploaded_at__gte=half_hour_ago)
.filter(uploaded_at__lte=a_quarter_hr_ago)
.filter(request__created_at__lte=half_hour_ago)
.order_by("request")
.select_related("request")
)
groups = groupby(files, key=lambda file: file.request)
for request, files in groups:
emails = request.get_requester_emails()
faq_url = reverse("faq")
contact_url = reverse("contact_us")
file_upload_url = reverse(
"request_eval_wizard_step_3", args=[request.reference]
)
context = {
"reference": request.reference,
"address": request.address,
"application_number": request.application_number,
"faq_url": f"{base_url}{faq_url}",
"contact_url": f"{base_url}{contact_url}",
"file_upload_url": f"{base_url}{file_upload_url}",
}
body = render_to_string(
"evaluations/emails/new_files_user_alert.txt", context=context
)
email = EmailMultiAlternatives(
subject="[EnvErgo] Votre mise à jour de documents",
body=body,
from_email=settings.DEFAULT_FROM_EMAIL,
to=emails,
)
email.send()
9 changes: 9 additions & 0 deletions envergo/evaluations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,15 @@ def is_from_instructor(self):
"""Shortcut property"""
return self.user_type == USER_TYPES.instructor

def get_requester_emails(self):
"""Return emails of the user who requested the evaluation."""

return (
self.urbanism_department_emails
if self.is_from_instructor()
else self.project_owner_emails
)

def create_evaluation(self):
"""Create an evaluation from this evaluation request."""

Expand Down
2 changes: 1 addition & 1 deletion envergo/evaluations/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def confirm_request_to_requester(request_id, host):
logger.info(f"Sending confirmation email to requester {request_id}")
request = Request.objects.filter(id=request_id).first()
delay_mention = get_setting("evalreq_confirmation_email_delay_mention")
user_emails = request.urbanism_department_emails
user_emails = request.get_requester_emails()
faq_url = reverse("faq")
contact_url = reverse("contact_us")
file_upload_url = reverse("request_eval_wizard_step_3", args=[request.reference])
Expand Down
98 changes: 86 additions & 12 deletions envergo/evaluations/tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
pytestmark = pytest.mark.django_db


@pytest.fixture
def time_10min_ago():
return localtime() - timedelta(minutes=10)


@pytest.fixture
def time_20min_ago():
return localtime() - timedelta(minutes=20)


@pytest.fixture
def time_45min_ago():
return localtime() - timedelta(minutes=45)
Expand All @@ -25,48 +35,112 @@ def time_3h_ago():
return localtime() - timedelta(hours=3)


@patch("envergo.evaluations.management.commands.new_files_alert.notify")
def test_new_files_alert_with_new_requests(mock_notify):
@patch("envergo.evaluations.management.commands.new_files_admin_alert.notify")
def test_new_files_admin_alert_with_new_requests(mock_notify):
"""When a request was just created, no alert is sent."""
request = RequestFactory()
RequestFileFactory(request=request)
call_command("new_files_alert")
call_command("new_files_admin_alert")

mock_notify.assert_not_called()


@patch("envergo.evaluations.management.commands.new_files_alert.notify")
def test_new_files_alert_with_new_file_lt_1hr_ago(
@patch("envergo.evaluations.management.commands.new_files_admin_alert.notify")
def test_new_files_admin_alert_with_new_file_lt_1hr_ago(
mock_notify, time_3h_ago, time_45min_ago
):
"""When a file was just uploaded, no alert is sent."""

request = RequestFactory(created_at=time_3h_ago)
RequestFileFactory(request=request, uploaded_at=time_45min_ago)
call_command("new_files_alert")
call_command("new_files_admin_alert")

mock_notify.assert_not_called()


@patch("envergo.evaluations.management.commands.new_files_alert.notify")
def test_new_files_alert_with_new_file_gt_1hr_ago(
@patch("envergo.evaluations.management.commands.new_files_admin_alert.notify")
def test_new_files_admin_alert_with_new_file_gt_1hr_ago(
mock_notify, time_3h_ago, time_1h30_ago
):
"""When a file was uploaded recently than 1hr, no alert is sent."""

request = RequestFactory(created_at=time_3h_ago)
RequestFileFactory(request=request, uploaded_at=time_1h30_ago)
call_command("new_files_alert")
call_command("new_files_admin_alert")

mock_notify.assert_called_once()


@patch("envergo.evaluations.management.commands.new_files_alert.notify")
def test_new_files_alert_with_old_file(mock_notify, time_3h_ago):
@patch("envergo.evaluations.management.commands.new_files_admin_alert.notify")
def test_new_files_admin_alert_with_old_file(mock_notify, time_3h_ago):
"""When a file was uploaded a while ago, no alert is sent."""

request = RequestFactory(created_at=time_3h_ago)
RequestFileFactory(request=request, uploaded_at=time_3h_ago)
call_command("new_files_alert")
call_command("new_files_admin_alert")

mock_notify.assert_not_called()


def test_new_files_user_alert_with_new_requests(mailoutbox):
"""When a request was just created, no alert is sent to user."""
request = RequestFactory()
RequestFileFactory(request=request)
call_command("new_files_user_alert")

assert len(mailoutbox) == 0


def test_new_files_user_alert_with_new_file_lt_15min_ago(
mailoutbox, time_1h30_ago, time_10min_ago
):
"""When a file was just uploaded, no alert is sent."""

request = RequestFactory(created_at=time_1h30_ago)
RequestFileFactory(request=request, uploaded_at=time_10min_ago)
call_command("new_files_user_alert")

assert len(mailoutbox) == 0


def test_new_files_user_alert_with_new_file_gt_15min_ago(
mailoutbox, time_1h30_ago, time_20min_ago
):
"""When a file was uploaded more than 15min ago, an alert is sent."""

request = RequestFactory(created_at=time_1h30_ago)
RequestFileFactory(request=request, uploaded_at=time_20min_ago)
call_command("new_files_user_alert")

assert len(mailoutbox) == 1


def test_new_files_user_alert_with_new_file_gt_30min_ago(
mailoutbox, time_1h30_ago, time_45min_ago
):
"""File uploaded more than 30min ago, it's too late, no alert is sent."""

request = RequestFactory(created_at=time_1h30_ago)
RequestFileFactory(request=request, uploaded_at=time_45min_ago)
call_command("new_files_user_alert")

assert len(mailoutbox) == 0


def test_new_files_user_alert_recipient(mailoutbox, time_1h30_ago, time_20min_ago):
"""The mail is sent to the right recipients."""

request = RequestFactory(user_type="instructor", created_at=time_1h30_ago)
RequestFileFactory(request=request, uploaded_at=time_20min_ago)
call_command("new_files_user_alert")

assert len(mailoutbox) == 1
email = mailoutbox[0]
assert email.to == ["instructor@example.org"]

request.user_type = "petitioner"
request.save()
call_command("new_files_user_alert")
assert len(mailoutbox) == 2
email = mailoutbox[1]
assert email.to == ["sponsor1@example.org", "sponsor2@example.org"]
43 changes: 42 additions & 1 deletion envergo/evaluations/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def test_eval_wizard_all_steps(
data = {
"project_description": "Bla bla bla",
"user_type": "instructor",
"urbanism_department_emails": ["contact@example.org"],
"urbanism_department_emails": ["urbanism@example.org"],
"project_owner_emails": "sponsor1@example.org,sponsor2@example.org",
"project_owner_phone": "0612345678",
}
Expand All @@ -265,11 +265,52 @@ def test_eval_wizard_all_steps(
assert len(callbacks) == 1
mock_post.assert_called_once()
assert len(mailoutbox) == 1
assert mailoutbox[0].to == ["urbanism@example.org"]
assert "Vous recevrez une réponse dans les trois jours ouvrés" in mailoutbox[0].body
evalreq.refresh_from_db()
assert evalreq.submitted is True


def test_eval_wizard_request_confirmation_recipient(
settings,
client,
mailoutbox,
django_capture_on_commit_callbacks,
moulinette_config,
):
"""When the user is the petitioner, the confirmation email is sent to the project owner."""
settings.MATTERMOST_ENDPOINT = "https://example.org/mattermost-endpoint/"

qs = Request.objects.all()
assert qs.count() == 0

url = reverse("request_eval_wizard_step_1")
data = {
"address": "42 rue du Test, 44000 Testville",
"project_description": "Bla bla bla",
}
res = client.post(url, data=data)
url = reverse("request_eval_wizard_step_2")
data = {
"user_type": "petitioner",
"send_eval_to_project_owner": True,
"project_owner_emails": "sponsor1@example.org,sponsor2@example.org",
"project_owner_phone": "0612345678",
}
res = client.post(url, data=data)
assert res.status_code == 302

evalreq = qs[0]
url = reverse("request_eval_wizard_step_3", args=[evalreq.reference])
with django_capture_on_commit_callbacks(execute=True) as callbacks:
res = client.post(url, data=data)
assert res.status_code == 302

assert len(callbacks) == 1
assert len(mailoutbox) == 1
assert mailoutbox[0].to == ["sponsor1@example.org", "sponsor2@example.org"]


@patch("envergo.utils.mattermost.requests.post")
def test_eval_is_only_submitted_once(
mock_post,
Expand Down
17 changes: 17 additions & 0 deletions envergo/templates/evaluations/emails/new_files_user_alert.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Bonjour,

Votre modification des documents attachés à la demande d'avis réglementaire {{ reference}} ({{ address }}) a bien été prise en compte.

Vous pouvez ajouter ou retirer des documents à votre demande :

{{ file_upload_url }}

Notre page d'information sur les réglementations environnementales est consultable :

{{ faq_url }}

N'hésitez pas à nous contacter pour toute question sur cette demande d'avis réglementaire ou sur EnvErgo.

{{ contact_url }}

{% include 'emails/_email_signature.txt' %}
Loading