from django import http from django.contrib.auth.mixins import UserPassesTestMixin from django.shortcuts import get_object_or_404, render from django.urls import reverse, reverse_lazy from django.views import generic from ..models import GroupedOrder, Order, OrderAuthor, OrderedItem def place_order(request, grouped_order_id): """Creates an AnonymousUser, and an Order for this GroupedOrder, with related OrderedItems""" grouped_order = get_object_or_404(GroupedOrder, pk=grouped_order_id) # check if the grouped order is ongoing or if the user is allowed to order user_is_orga = request.user == grouped_order.orga is_to_be_delivered = grouped_order.is_to_be_delivered() is_ongoing = grouped_order.is_ongoing() access_allowed = is_ongoing or (user_is_orga and is_to_be_delivered) if not access_allowed: return http.HttpResponseForbidden() # get a dict with quantity_{{item_id}}:[ {{ quantity on phone }},{{ quantity on desktop }} ] orders_dict = { key: request.POST.getlist(key) for key, value in request.POST.items() if key.startswith("quantity") } # transform it into quantity_{{item_id}}: {{ greatest of the two quantities }} for i in orders_dict: value = ( orders_dict[i][0] if orders_dict[i][0] >= orders_dict[i][1] else orders_dict[i][1] ) orders_dict[i] = value # create an order first_name = request.POST["first_name"] last_name = request.POST["last_name"] phone = request.POST["phone"] email = request.POST["email"] note = request.POST["note"] author = OrderAuthor.objects.create( first_name=first_name, last_name=last_name, email=email, phone=phone ) order = Order.objects.create(author=author, grouped_order=grouped_order, note=note) # add items to the order error_message = None for key, quantity in orders_dict.items(): quantity = int(quantity) item = grouped_order.item_set.get(pk=key.split("_")[1]) # check if too many items are ordered error_message = validate_item_ordered_nb(item, quantity) if error_message: break # stop creating items if there is an error if quantity > 0: OrderedItem.objects.create(nb=quantity, order=order, item=item) # Redisplay the form with error messages if there is an error if error_message: order.delete() author.delete() grouped_order.compute_items_ordered_nb() return render( request, "order/grouped_order_detail.html", { "grouped_order": grouped_order, "error_message": error_message, "note": order.note, "author": author, }, ) # check if the order contains articles error_message = validate_articles_ordered_nb(order) # Redisplay the form with error messages if there is an error if error_message: order.delete() author.delete() return render( request, "order/grouped_order_detail.html", { "grouped_order": grouped_order, "error_message": error_message, "note": order.note, "author": author, }, ) # Redirect to confirmation page order.compute_order_price() grouped_order.compute_items_ordered_nb() # 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. return http.HttpResponseRedirect( reverse("order:order_confirm", args=(grouped_order.pk, order.pk)) ) def validate_item_ordered_nb(item, ordered_nb): """Returns an error message if the ordered items are not available""" if item.get_remaining_nb() is not None and item.get_remaining_nb() - ordered_nb < 0: return f"Trop de {item.name} commandés pour la quantité disponible" return None def validate_articles_ordered_nb(order): """Return an error if no items are ordered""" order.compute_order_articles_nb() if order.articles_nb == 0: return "Veuillez commander au moins un produit" return None class OrderDetailView(generic.DetailView): """Confirmation page after a user orders""" model = Order class OrderDeleteView(UserPassesTestMixin, generic.DeleteView): """DeleteView for an order""" model = Order def get_success_url(self): return reverse_lazy( "order:grouped_order_overview", args=[self.object.grouped_order.id] ) def test_func(self): """Accessible only if the requesting user is the grouped order organizer""" return self.get_object().grouped_order.orga == self.request.user