Add the ability to use a code to join an order.

This commit is contained in:
Alexis Métaireau 2023-08-14 17:36:13 +02:00
parent cf2c79cc3f
commit b4bdfb8cf4
8 changed files with 100 additions and 8 deletions

View file

@ -80,3 +80,15 @@ class ItemCreateForm(forms.ModelForm):
def save(self, commit=True):
self.instance.grouped_order = GroupedOrder.objects.get(id=self.grouped_order.pk)
return super().save(commit=commit)
class JoinGroupedOrderForm(forms.Form):
code = forms.CharField(label="Code pour rejoindre la commande", max_length=6)
def clean_code(self):
form_code = self.cleaned_data["code"]
if not GroupedOrder.objects.filter(code=form_code).exists():
raise forms.ValidationError(
"Désolé, nous ne trouvons aucune commande avec ce code"
)
return form_code

View file

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% block title %}Rejoindre une commande{% endblock %}
{% block content %}
<p class="desktop-hidden mobile-content-title">
{% block content_title %}Rejoindre une commande groupée{% endblock %}
</p>
<div class="box">
<div class="columns">
<div class="column is-8">
<h3>Utiliser un code</h3>
<p>Si vous avez un code pour rejoindre une distribution, entrez-le ici.</p>
<form method="post">
{% csrf_token %}
{% for error in form.code.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
<div class="field has-addons">
<div class="control">
<input name="code" class="input {% if form.code.errors %}is-danger{% endif %}" type="text">
</div>
<div class="control">
<input class="button is-primary" type="submit" value="Rejoindre">
</div>
</div>
</div>
</form>
</div>
</div>
<div class="box">
<h4>Vous avez un lien ?</h4>
<p>Si vous avez reçu un lien par un organisateur ou une organisatrice de commande, vous pouvez coller ce lien dans
la barre de navigation en haut de l'écran !</p>
</div>
<p>Sinon, vous pouvez vous <a href="{% url 'accounts:signup' %}">créer un compte</a> ou <a
href="{% url 'accounts:login' %}">vous connecter</a>
pour organiser une nouvelle commande groupée.
</div>
{% endblock %}

View file

@ -190,6 +190,35 @@ class TestGroupedOrderIndexView:
)
class TestJoinGroupedOrderView:
def test_correct_code_redirects_properly(self, client, client_log):
logged_user = auth.get_user(client_log)
grouped_order = create_grouped_order(
days_before_delivery_date=5,
days_before_deadline=2,
name="test",
orga_user=logged_user,
)
join_url = reverse("order:grouped_order_join")
response = client.post(join_url, {"code": grouped_order.code})
expected_url = reverse(
"order:grouped_order_detail", kwargs={"code": grouped_order.code}
)
assert response.status_code == 302
assert response.url == expected_url
def test_incorrect_code_errors_out(self, client):
assert len(models.GroupedOrder.objects.all()) == 0
join_url = reverse("order:grouped_order_join")
response = client.post(join_url, {"code": "123456"})
assert (
"nous ne trouvons aucune commande avec ce code" in response.content.decode()
)
class TestGroupedOrderDetailView:
def test_order_item(self, client, other_user):
"""

View file

@ -1,4 +1,3 @@
# fmt: off
import datetime
import pytest
@ -12,7 +11,6 @@ from la_chariotte.order.tests.utils import (
order_items_in_grouped_order,
)
# fmt: on
pytestmark = pytest.mark.django_db

View file

@ -13,9 +13,6 @@ pytestmark = pytest.mark.django_db
def create_grouped_order(
days_before_delivery_date, days_before_deadline, name, orga_user
):
"""
Creates a grouped order.
"""
date = timezone.now().date() + datetime.timedelta(days=days_before_delivery_date)
deadline = timezone.now() + datetime.timedelta(days=days_before_deadline)
grouped_order = models.GroupedOrder.objects.create(

View file

@ -8,7 +8,7 @@ urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path(
"rejoindre-une-commande",
TemplateView.as_view(template_name="order/grouped_order_join.html"),
views.JoinGroupedOrderView.as_view(),
name="grouped_order_join",
),
path(

View file

@ -11,6 +11,7 @@ from .grouped_order import (
GroupedOrderOverview,
GroupedOrderUpdateView,
IndexView,
JoinGroupedOrderView,
)
from .item import ItemCreateView, ItemDeleteView
from .order import OrderDeleteView, OrderDetailView, place_order

View file

@ -5,7 +5,7 @@ from io import BytesIO
from django import http
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.core.serializers.json import DjangoJSONEncoder
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, redirect
from django.template.loader import get_template
from django.urls import reverse, reverse_lazy
from django.utils import timezone
@ -14,7 +14,7 @@ from django_weasyprint import WeasyTemplateResponseMixin
from django_weasyprint.views import WeasyTemplateResponse, WeasyTemplateView
from xhtml2pdf import pisa
from ..forms import GroupedOrderForm, Item
from ..forms import GroupedOrderForm, Item, JoinGroupedOrderForm
from ..models import GroupedOrder, OrderAuthor
@ -52,6 +52,18 @@ class IndexView(LoginRequiredMixin, generic.ListView):
}
class JoinGroupedOrderView(generic.FormView, generic.RedirectView, LoginRequiredMixin):
form_class = JoinGroupedOrderForm
template_name = "order/grouped_order_join.html"
def form_valid(self, form):
return redirect(
reverse_lazy(
"order:grouped_order_detail", kwargs={"code": form.cleaned_data["code"]}
)
)
class GroupedOrderDetailView(generic.DetailView):
model = GroupedOrder
template_name = "order/grouped_order_detail.html"