diff --git a/README.md b/README.md index cb6e886..b2426d5 100644 --- a/README.md +++ b/README.md @@ -158,12 +158,22 @@ Si il y a des erreurs BLACK, on peut lancer black pour linter le code : black . ``` +## Tests de l'envoi de mails + +Pour tester l'apparence des mails, on peut utiliser Sendria : +```bash +pip install sendria +sendria --db mails.sqlite +$NAVIGATOR http://127.0.0.1:1080 +``` + ## Architecture de l'application Les différentes applications Django créées sont : - ``Order``, pour gérer tout ce qui tourne autour des commandes - ``Accounts``, pour gérer la création de comptes. Pour la connexion, la déconnexion et le changement de mot de passe, on utilise l'application auth intégrée à Django. +- ``mail``, pour l'envoi des mails. A l'état actuel, le diagramme de classes est le suivant : diff --git a/la_chariotte/helpers/fixtures.py b/la_chariotte/helpers/fixtures.py index 2aa45d3..e7375b0 100644 --- a/la_chariotte/helpers/fixtures.py +++ b/la_chariotte/helpers/fixtures.py @@ -1,4 +1,9 @@ +import datetime + import pytest +from django.utils import timezone + +from la_chariotte.order.models import GroupedOrder, Item @pytest.fixture @@ -16,3 +21,17 @@ def other_user(django_user_model): password = "azertypassword" user = django_user_model.objects.create_user(username=username, password=password) return user + + +@pytest.fixture +def simple_grouped_order(other_user): + date = timezone.now().date() + datetime.timedelta(days=30) + deadline = timezone.now() + datetime.timedelta(days=5) + grouped_order = GroupedOrder.objects.create( + name="Test grouped order", + orga=other_user, + delivery_date=date, + deadline=deadline, + ) + item = Item.objects.create(name="test item", grouped_order=grouped_order, price=2) + return grouped_order diff --git a/la_chariotte/mail/__init__.py b/la_chariotte/mail/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/la_chariotte/mail/apps.py b/la_chariotte/mail/apps.py new file mode 100644 index 0000000..6230dde --- /dev/null +++ b/la_chariotte/mail/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MailConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "la_chariotte.mail" diff --git a/la_chariotte/mail/templates/mail/order_confirm_mail.html b/la_chariotte/mail/templates/mail/order_confirm_mail.html new file mode 100644 index 0000000..8ffb3c3 --- /dev/null +++ b/la_chariotte/mail/templates/mail/order_confirm_mail.html @@ -0,0 +1,91 @@ +{% load i18n static %} + + + + + + + + + +
+ + + + +

Merci, {{ order.author.first_name }} !

+

Votre participation à la commande groupée "{{ order.grouped_order }}" a bien été confirmée.

+ +

Votre commande :

+ +

Prix total de la commande : {{ order.price }} € +

Le paiement n'est pas (encore) pris en charge par la Chariotte. C'est l'organisateur·ice de la commande qui doit vous indiquer les moyens de paiement.

+ + +

Rendez-vous le {{ order.grouped_order.delivery_date }}{% if order.grouped_order.place %} à {{ order.grouped_order.place }}{% endif %} pour récupérer vos produits !

+ +

Pour toute question, vous pouvez contacter l'organisateur·ice de la commande, {{ order.grouped_order.orga }} : + Envoyer un mail

+ +
+ + Voir la page de commande + +
+ + + + \ No newline at end of file diff --git a/la_chariotte/mail/test_mail.py b/la_chariotte/mail/test_mail.py new file mode 100644 index 0000000..048639c --- /dev/null +++ b/la_chariotte/mail/test_mail.py @@ -0,0 +1,41 @@ +import pytest +from django.urls import reverse + +from la_chariotte import settings +from la_chariotte.order.models import GroupedOrder + +pytestmark = pytest.mark.django_db + + +def test_send_order_confirmation_mail(mailoutbox, simple_grouped_order, client): + """ + When a user orders, they receive a confirmation email + """ + item = simple_grouped_order.item_set.first() + + # the user places an order + order_url = reverse( + "order:order", + kwargs={ + "grouped_order_id": simple_grouped_order.pk, + }, + ) + response = client.post( + order_url, + { + f"quantity_{item.pk}": [4, 0], + "first_name": "Prénom", + "last_name": "Nom", + "phone": "0645632569", + "email": "test@mail.fr", + "note": "", + }, + ) + assert len(mailoutbox) == 1 + m = mailoutbox[0] + assert m.subject == "[La Chariotte] Votre commande pour Test grouped order" + assert "Votre participation à la commande groupée" in m.body + assert "Votre participation à la commande groupée" in m.alternatives[0][0] + assert f"{settings.BASE_URL}" in m.alternatives[0][0] + assert m.alternatives[0][1] == "text/html" + assert "test@mail.fr" in mailoutbox[0].to diff --git a/la_chariotte/mail/utils.py b/la_chariotte/mail/utils.py new file mode 100644 index 0000000..0fadd65 --- /dev/null +++ b/la_chariotte/mail/utils.py @@ -0,0 +1,19 @@ +from django.core import mail +from django.template.loader import render_to_string +from django.utils.html import strip_tags + +from la_chariotte import settings + + +def send_order_confirmation_mail(order): + template_name = "mail/order_confirm_mail.html" + + subject = f"[La Chariotte] Votre commande pour {order.grouped_order.name}" + html_message = render_to_string( + template_name, {"order": order, "base_url": settings.BASE_URL} + ) + plain_message = strip_tags(html_message) + from_email = "notification@chariotte.fr" + to = order.author.email + + mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message) diff --git a/la_chariotte/order/templates/order/order_detail.html b/la_chariotte/order/templates/order/order_detail.html index 271c92e..4ff94c4 100644 --- a/la_chariotte/order/templates/order/order_detail.html +++ b/la_chariotte/order/templates/order/order_detail.html @@ -8,17 +8,16 @@

Merci, {{ order.author.first_name }} !

-

Votre participation à la commande groupée "{{ order.grouped_order }}" a bien été confirmée ! - Dans une prochaine version de la Chariotte, vous recevrez un mail de confirmation :)

-

En attendant, vous pouvez bien noter ces infos :

+

Votre participation à la commande groupée "{{ order.grouped_order }}" a bien été confirmée et vous avez normalement reçu un mail de confirmation. -

Votre commande

+

Votre commande :

Prix total de la commande : {{ order.price }} € +

Le paiement n'est pas (encore) pris en charge par la Chariotte. C'est l'organisateur·ice de la commande qui doit vous indiquer les moyens de paiement.

Rendez-vous le {{ order.grouped_order.delivery_date }}{% if order.grouped_order.place %} à {{ order.grouped_order.place }}{% endif %} pour récupérer vos produits !

diff --git a/la_chariotte/order/views/order.py b/la_chariotte/order/views/order.py index 42543df..08735c6 100644 --- a/la_chariotte/order/views/order.py +++ b/la_chariotte/order/views/order.py @@ -4,6 +4,8 @@ from django.shortcuts import get_object_or_404, render from django.urls import reverse, reverse_lazy from django.views import generic +from la_chariotte.mail.utils import send_order_confirmation_mail + from ..models import GroupedOrder, Order, OrderAuthor, OrderedItem @@ -94,9 +96,11 @@ def place_order(request, code): }, ) - # Redirect to confirmation page + # Send confirmation mail and redirect to confirmation page order.compute_order_price() grouped_order.compute_items_ordered_nb() + send_order_confirmation_mail(order) + # Always return an http.HttpResponseRedirect after successfully dealing # with POST data. This prevents data from being posted twice if a # user hits the Back button. diff --git a/la_chariotte/settings.py b/la_chariotte/settings.py index f9595d3..2bfbc6d 100644 --- a/la_chariotte/settings.py +++ b/la_chariotte/settings.py @@ -40,6 +40,7 @@ if os.getenv("ALLOWED_HOSTS"): INSTALLED_APPS = [ "la_chariotte.order", "la_chariotte.accounts", + "la_chariotte.mail", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes",