diff --git a/la_chariotte/order/templates/order/index.html b/la_chariotte/order/templates/order/index.html
index e15311b..a962667 100644
--- a/la_chariotte/order/templates/order/index.html
+++ b/la_chariotte/order/templates/order/index.html
@@ -21,7 +21,7 @@
Livraison |
Fin des commandes |
Nombre de commandes |
- Voir |
+ |
@@ -34,12 +34,17 @@
{{ gr_order.delivery_date }} |
{{ gr_order.deadline }} |
{{ gr_order.order_set.count }} |
-
+ |
+
-
-
-
- |
+
+
+
+
+
+
+
+
{% endfor %}
@@ -54,7 +59,7 @@
Livraison |
Fin des commandes |
Nombre de commandes |
- Voir |
+ |
@@ -67,12 +72,17 @@
{{ gr_order.delivery_date }} |
{{ gr_order.deadline }} |
{{ gr_order.order_set.count }} |
-
+ |
+
-
-
-
- |
+
+
+
+
+
+
+
+
{% endfor %}
@@ -87,7 +97,7 @@
Livraison |
Fin des commandes |
Nombre de commandes |
- Voir |
+ |
@@ -100,12 +110,17 @@
{{ gr_order.delivery_date }} |
{{ gr_order.deadline }} |
{{ gr_order.order_set.count }} |
-
+ |
+
-
-
-
- |
+
+
+
+
+
+
+
+
{% endfor %}
diff --git a/la_chariotte/order/tests/test_views.py b/la_chariotte/order/tests/test_views.py
index a5012fd..6a092a5 100644
--- a/la_chariotte/order/tests/test_views.py
+++ b/la_chariotte/order/tests/test_views.py
@@ -1288,6 +1288,90 @@ class TestGroupedOrderDeleteView:
assert models.GroupedOrder.objects.count() == 1
+class TestGroupedOrderDuplicateView:
+ def test_duplicate_grouped_order(self, client_log):
+ """The orga of the GO duplicates it.
+ A new GO is created without any order but with the same item_set.
+ The user gets redirected to the update view. The old GO remains the same"""
+ grouped_order = create_grouped_order(
+ days_before_delivery_date=5,
+ days_before_deadline=2,
+ name="gr order test",
+ orga_user=auth.get_user(client_log),
+ )
+ assert models.GroupedOrder.objects.count() == 1
+ order = order_items_in_grouped_order(grouped_order)
+ assert models.Item.objects.count() == 2
+ assert models.OrderedItem.objects.count() == 2
+ assert models.OrderAuthor.objects.count() == 1
+ assert grouped_order.item_set.first().ordered_nb == 3
+
+ # duplicate
+ duplicate_view_url = reverse(
+ "order:duplicate_grouped_order", kwargs={"pk": grouped_order.pk}
+ )
+ response = client_log.get(duplicate_view_url)
+ assert models.GroupedOrder.objects.count() == 2
+ new_grouped_order = models.GroupedOrder.objects.all()[1]
+ assert new_grouped_order.name == "gr order test - copie"
+ assert new_grouped_order.delivery_date == grouped_order.delivery_date
+ assert new_grouped_order.deadline == grouped_order.deadline
+ assert new_grouped_order.place == grouped_order.place
+ assert new_grouped_order.orga == auth.get_user(client_log)
+ assert new_grouped_order.description == grouped_order.description
+ assert new_grouped_order.item_set.count() == grouped_order.item_set.count()
+ assert new_grouped_order.item_set.first().ordered_nb == 0
+ assert models.GroupedOrder.objects.count() == 2
+
+ # redirection
+ assert response.status_code == 302
+ assert response.url == reverse(
+ "order:update_grouped_order", kwargs={"pk": new_grouped_order.pk}
+ )
+
+ # The initial grouped order did not change
+ assert grouped_order.item_set.first().ordered_nb == 3
+
+ def test_duplicate_grouped_order__not_orga(self, client_log, other_user):
+ """A user that is not orga gets the duplicate view. They get a 403 error."""
+ grouped_order = create_grouped_order(
+ days_before_delivery_date=5,
+ days_before_deadline=2,
+ name="gr order test",
+ orga_user=other_user,
+ )
+ assert models.GroupedOrder.objects.count() == 1
+
+ # get the duplicate view
+ duplicate_view_url = reverse(
+ "order:duplicate_grouped_order", kwargs={"pk": grouped_order.pk}
+ )
+ response = client_log.get(duplicate_view_url)
+ assert response.status_code == 403
+
+ assert models.GroupedOrder.objects.count() == 1
+
+ def test_duplicate_grouped_order__anonymous(self, client, other_user):
+ """An anonymous user gets the duplicate view. They get redirected to login page"""
+ grouped_order = create_grouped_order(
+ days_before_delivery_date=5,
+ days_before_deadline=2,
+ name="gr order test",
+ orga_user=other_user,
+ )
+ assert models.GroupedOrder.objects.count() == 1
+
+ # get the duplicate view
+ duplicate_view_url = reverse(
+ "order:duplicate_grouped_order", kwargs={"pk": grouped_order.pk}
+ )
+ response = client.get(duplicate_view_url)
+ assert response.status_code == 302
+ assert response.url == f"{reverse('accounts:login')}?next={duplicate_view_url}"
+
+ assert models.GroupedOrder.objects.count() == 1
+
+
class TestItemCreateView:
def test_create_item(self, client_log):
"""A user that has created a grouped order adds an item to it."""
diff --git a/la_chariotte/order/urls.py b/la_chariotte/order/urls.py
index f31d2f8..397d6fe 100644
--- a/la_chariotte/order/urls.py
+++ b/la_chariotte/order/urls.py
@@ -35,6 +35,11 @@ urlpatterns = [
views.GroupedOrderDeleteView.as_view(),
name="delete_grouped_order",
),
+ path(
+ "/dupliquer",
+ views.GroupedOrderDuplicateView.as_view(),
+ name="duplicate_grouped_order",
+ ),
path(
"/gerer-produits/nouveau",
views.ItemCreateView.as_view(),
diff --git a/la_chariotte/order/views/__init__.py b/la_chariotte/order/views/__init__.py
index 7cceb7d..1acbe58 100644
--- a/la_chariotte/order/views/__init__.py
+++ b/la_chariotte/order/views/__init__.py
@@ -2,8 +2,9 @@
from .grouped_order import (ExportGroupedOrderEmailAddressesToCSVView,
GroupedOrderAddItemsView, GroupedOrderCreateView,
GroupedOrderDeleteView, GroupedOrderDetailView,
- GroupedOrderOverview, GroupedOrderSheetView,
- GroupedOrderUpdateView, IndexView)
+ GroupedOrderDuplicateView, GroupedOrderOverview,
+ GroupedOrderSheetView, GroupedOrderUpdateView,
+ IndexView)
from .item import ItemCreateView, ItemDeleteView
from .order import OrderDetailView, order
diff --git a/la_chariotte/order/views/grouped_order.py b/la_chariotte/order/views/grouped_order.py
index 545d43f..080b206 100644
--- a/la_chariotte/order/views/grouped_order.py
+++ b/la_chariotte/order/views/grouped_order.py
@@ -129,6 +129,49 @@ class GroupedOrderUpdateView(UserPassesTestMixin, generic.UpdateView):
return kwargs
+class GroupedOrderDuplicateView(UserPassesTestMixin, generic.RedirectView):
+ """View for duplicating an existing grouped order : the groupedOrder is duplicated
+ and the user is redirected to the new grouped order update view"""
+
+ # url = reverse_lazy("order:update_grouped_order", args=(self.get_object().pk,))
+
+ def test_func(self):
+ """Accessible only if the requesting user is the grouped order organizer"""
+ initial_grouped_order_id = self.kwargs.get("pk")
+ return (
+ GroupedOrder.objects.get(pk=initial_grouped_order_id).orga
+ == self.request.user
+ )
+
+ def get(self, request, *args, **kwargs):
+ # overwrite the get function to copy the initial grouped order before redirecting to
+ # the update view of the new grouped order
+ initial_grouped_order = GroupedOrder.objects.get(pk=self.kwargs.get("pk"))
+ new_grouped_order = GroupedOrder.objects.create(
+ name=f"{initial_grouped_order.name} - copie",
+ orga=self.request.user,
+ delivery_date=initial_grouped_order.delivery_date,
+ deadline=initial_grouped_order.deadline,
+ place=initial_grouped_order.place,
+ description=initial_grouped_order.description,
+ )
+ # duplicate each item and add it to new_grouped_order
+ for item in initial_grouped_order.item_set.all():
+ item.pk = None
+ item.ordered_nb = 0
+ item.save()
+ new_grouped_order.item_set.add(item)
+
+ self.kwargs["new_go_id"] = new_grouped_order.pk
+
+ return super().get(request, *args, **kwargs)
+
+ def get_redirect_url(self, *args, **kwargs):
+ return reverse_lazy(
+ "order:update_grouped_order", kwargs={"pk": self.kwargs["new_go_id"]}
+ )
+
+
class GroupedOrderDeleteView(UserPassesTestMixin, generic.DeleteView):
"""View for deleting a grouped order"""