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"""