diff --git a/shop/admin.py b/shop/admin.py index 431b24c9..583dc0ea 100644 --- a/shop/admin.py +++ b/shop/admin.py @@ -45,6 +45,7 @@ class OrderAdmin(admin.ModelAdmin): 'camp', 'payment_method', 'paid', + 'cancelled', ] list_filter = [ diff --git a/shop/managers.py b/shop/managers.py index cd4f9a32..349cfe16 100644 --- a/shop/managers.py +++ b/shop/managers.py @@ -11,3 +11,21 @@ class ProductQuerySet(QuerySet): return self.filter( available_in__contains=DateTimeTZRange(now, None) ) + + +class OrderQuerySet(QuerySet): + + def not_cancelled(self): + return self.filter(cancelled=False) + + def open(self): + return self.filter(open__isnull=True) + + def paid(self): + return self.filter(paid=True) + + def unpaid(self): + return self.filter(paid=False) + + def cancelled(self): + return self.filter(cancelled=True) diff --git a/shop/migrations/0023_order_cancelled.py b/shop/migrations/0023_order_cancelled.py new file mode 100644 index 00000000..c858e833 --- /dev/null +++ b/shop/migrations/0023_order_cancelled.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-06-01 08:53 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shop', '0022_auto_20160530_2301'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='cancelled', + field=models.BooleanField(default=False), + ), + ] diff --git a/shop/models.py b/shop/models.py index ede52c19..4c942691 100644 --- a/shop/models.py +++ b/shop/models.py @@ -8,7 +8,7 @@ from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from django.core.urlresolvers import reverse_lazy from utils.models import UUIDModel, CreatedUpdatedModel -from .managers import ProductQuerySet +from .managers import ProductQuerySet, OrderQuerySet import hashlib, io, base64, qrcode from decimal import Decimal from datetime import timedelta @@ -72,6 +72,10 @@ class Order(CreatedUpdatedModel): default=BLOCKCHAIN ) + cancelled = models.BooleanField(default=False) + + objects = OrderQuerySet.as_manager() + def __str__(self): return 'order id #%s' % self.pk @@ -160,6 +164,11 @@ class Order(CreatedUpdatedModel): else: return False + def mark_as_cancelled(self): + self.cancelled = True + self.open = None + self.save() + class ProductCategory(CreatedUpdatedModel, UUIDModel): class Meta: diff --git a/shop/templates/order_detail.html b/shop/templates/order_detail.html index 77a524bf..7adc87c2 100644 --- a/shop/templates/order_detail.html +++ b/shop/templates/order_detail.html @@ -6,7 +6,7 @@

Order #{{ order.id }}

-{% if not order.open == None %} +{% if not order.paid %}
{% csrf_token %} {% endif %} @@ -66,8 +66,11 @@ {% if not order.open == None %} - {% bootstrap_button "Update order" button_type="submit" button_class="btn-primary" name="update_order" %} - {% bootstrap_button "Cancel order" button_type="submit" button_class="btn-danger pull-right" name="cancel_order" %} + {% bootstrap_button "Update order" button_type="submit" button_class="btn-primary" name="update_order" %} +{% endif %} + +{% if not order.paid %} + {% bootstrap_button "Cancel order" button_type="submit" button_class="btn-danger" name="cancel_order" %} {% endif %}
diff --git a/shop/views.py b/shop/views.py index d64b32ea..96ea3e3a 100644 --- a/shop/views.py +++ b/shop/views.py @@ -106,6 +106,22 @@ class EnsureOrderHasProductsMixin(SingleObjectMixin): ) +class EnsureOrderIsNotCancelledMixin(SingleObjectMixin): + model = Order + + def dispatch(self, request, *args, **kwargs): + if self.get_object().cancelled: + messages.error( + request, + 'Order #{} is cancelled!'.format(self.get_object().id) + ) + return HttpResponseRedirect(reverse_lazy('shop:index')) + + return super(EnsureOrderHasProductsMixin, self).dispatch( + request, *args, **kwargs + ) + + class EnsureOrderHasInvoicePDFMixin(SingleObjectMixin): model = Order @@ -217,14 +233,20 @@ class ProductDetailView(FormView, DetailView): class OrderListView(LoginRequiredMixin, ListView): model = Order template_name = "order_list.html" + context_object_name = 'orders' - def get_context_data(self, **kwargs): - context = super(OrderListView, self).get_context_data(**kwargs) - context['orders'] = Order.objects.filter(user=self.request.user) - return context + def get_queryset(self): + queryset = super(OrderListView, self).get_queryset() + return queryset.filter(user=self.request.user).not_cancelled() -class OrderDetailView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureOrderHasProductsMixin, DetailView): +class OrderDetailView( + LoginRequiredMixin, + EnsureUserOwnsOrderMixin, + EnsureOrderHasProductsMixin, + EnsureOrderIsNotCancelledMixin, + DetailView +): model = Order template_name = 'order_detail.html' context_object_name = 'order' @@ -269,12 +291,12 @@ class OrderDetailView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureOrderH if product_remove: order.orderproductrelation_set.filter(pk=product_remove).delete() if not order.products.count() > 0: - order.delete() + order.mark_as_cancelled() messages.info(request, 'Order cancelled!') return HttpResponseRedirect(reverse_lazy('shop:index')) if 'cancel_order' in request.POST: - order.delete() + order.mark_as_cancelled() messages.info(request, 'Order cancelled!') return HttpResponseRedirect(reverse_lazy('shop:index'))