diff --git a/bornhack/templates/base.html b/bornhack/templates/base.html index d94c98b0..2e49af8e 100644 --- a/bornhack/templates/base.html +++ b/bornhack/templates/base.html @@ -40,7 +40,7 @@ {% if current_camp.shop_open %}
  • Shop
  • {% endif %} -
  • Good to know
  • +
  • Info
  • {% if user.is_authenticated %}
  • Profile
  • Logout
  • diff --git a/shop/forms.py b/shop/forms.py index 750c6555..1ae7cf09 100644 --- a/shop/forms.py +++ b/shop/forms.py @@ -6,3 +6,7 @@ class CheckoutForm(forms.Form): # no fields here, just three submit buttons pass +class AddToOrderForm(forms.Form): + # no fields, just a submit button + pass + diff --git a/shop/models.py b/shop/models.py index ac341672..f32dd3ca 100644 --- a/shop/models.py +++ b/shop/models.py @@ -2,9 +2,7 @@ from django.db import models from django.contrib.postgres.fields import DateTimeRangeField, JSONField from django.utils.translation import ugettext_lazy as _ from django.utils import timezone - from bornhack.utils import CreatedUpdatedModel, UUIDModel - from .managers import ProductQuerySet diff --git a/shop/templates/shop_index.html b/shop/templates/shop_index.html index fb4a9d19..01d2a9d0 100644 --- a/shop/templates/shop_index.html +++ b/shop/templates/shop_index.html @@ -1,13 +1,41 @@ {% extends 'base.html' %} - {% block content %}

    Shop

    -Here you can see the different products and prices. +Here you can see your orders and available products in the shop.

    +

    Orders

    + + + + + + + + + + + +{% for order in orders %} + + + + + + + +{% endfor %} + +
    Order IDOpen?Paid?Delivered?Actions
    {{ order.id }}{{ order.finalized }}{{ order.paid }}? + {% if order.finalized and not order.paid %} + {% bootstrap_button "Pay order" href="{% reverse 'shop:order_detail' pk=order.id %}" button_class="btn-primary" %} + {% bootstrap_button "Cancel order" href="{% reverse 'shop:order_cancel' pk=order.id %}" button_class="btn-primary" %} + {% endif %} +
    +

    Products

    @@ -17,7 +45,6 @@ Here you can see the different products and prices. - {% for product in product_list %} @@ -30,9 +57,7 @@ Here you can see the different products and prices. {% endfor %}
    Buy
    {% if product.is_available %} - - Add to order - + {% bootstrap_button "Add to order" href="{% reverse 'shop:product_detail' pk=product.id %}" button_class="btn-primary" %} {% else %} N/A {% endif %} @@ -41,5 +66,4 @@ Here you can see the different products and prices.
    - {% endblock %} diff --git a/shop/urls.py b/shop/urls.py index dc9019b8..92c58ec8 100644 --- a/shop/urls.py +++ b/shop/urls.py @@ -13,6 +13,7 @@ urlpatterns = [ #name='epay_callback' #), url(r'$', ShopIndexView.as_view(), name='index'), + url(r'products/(?P[0-9]+)/$', ProductDetailView.as_view(), name='product_detail'), url(r'orders/(?P[0-9]+)/$', OrderDetailView.as_view(), name='order_detail'), url(r'orders/(?P[0-9]+)/checkout/$', CheckoutView.as_view(), name='checkout'), ] diff --git a/shop/views.py b/shop/views.py index cbf0ea38..6a0b64b8 100644 --- a/shop/views.py +++ b/shop/views.py @@ -8,20 +8,48 @@ from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse from django.contrib import messages -from .models import Order, Product, EpayCallback, EpayPayment -from .forms import CheckoutForm +from .models import Order, Product, EpayCallback, EpayPayment, OrderProductRelation +from .forms import CheckoutForm, AddToOrderForm class ShopIndexView(ListView): model = Product template_name = "shop_index.html" + def get_context_data(self, **kwargs): + context = super(EpayView, self).get_context_data(**kwargs) + context['orders'] = Order.objects.filter(user=self.request.user) + return context -class ProductDetailView(LoginRequiredMixin, DetailView): + +class ProductDetailView(LoginRequiredMixin, FormView): model = Product template_name = 'product_detail.html' + form_class = 'AddToOrderForm' context_object_name = 'product' + def get(self, request, *args, **kwargs): + self.product == Product.objects.get(id=kwargs.get('product_id')) + + def form_valid(self, form): + ### do we have an open order? + try: + order = Order.objects.get(user=self.request.user, finalized=False) + except Order.DoesNotExist: + ### no open order - open a new one + order = Order.objects.create(user=request.user) + + ### get product from kwargs + product = Product.objects.get(id= + if self.product in order.products.all(): + ### this product is already added to this order, increase count by one + OrderProductRelation.objects.filter(product=self.product, order=order).update(quantity=F('quantity') + 1) + else: + order.products.add(self.product) + + ### done + return super(ProductDetailView, self).form_valid(form) + class OrderDetailView(LoginRequiredMixin, DetailView): model = Product @@ -36,6 +64,7 @@ class CheckoutView(LoginRequiredMixin, FormView): """ model = Order template_name = 'checkout.html' + form_class='CheckoutForm' context_object_name = 'order' def get(self, request, *args, **kwargs): @@ -43,17 +72,17 @@ class CheckoutView(LoginRequiredMixin, FormView): raise Http404("Order not found") if self.get_object().paid: - messages.error('This order is already paid for!') + messages.error(request, 'This order is already paid for!') return HttpResponseRedirect('shop:order_detail') if not self.get_object().products: - messages.error('This order contains no products!') + messages.error(request, 'This order contains no products!') return HttpResponseRedirect('shop:order_detail') return self.render_to_response(self.get_context_data()) def form_valid(self, form): - ### mark order as finalizedredirect user to payment + ### mark order as finalized and redirect user to payment form.instance.finalized=True ### set payment_method based on submit button used @@ -86,13 +115,33 @@ class CheckoutView(LoginRequiredMixin, FormView): class CoinifyRedirectView(TemplateView): template_name = 'coinify_redirect.html' + def get(self, request, *args, **kwargs): + ### validate a few things + self.order = Order.objects.get(pk=kwargs.get('order_id')) + if self.order.user != request.user: + raise Http404("Order not found") + + if not self.order.finalized: + messages.error(request, 'This order is still open!') + return HttpResponseRedirect('shop:order_detail') + + if self.order.paid: + messages.error(request, 'This order is already paid for!') + return HttpResponseRedirect('shop:order_detail') + + if not self.get_object().products: + messages.error(request, 'This order contains no products!') + return HttpResponseRedirect('shop:order_detail') + + return self.render_to_response(self.get_context_data()) + def get_context_data(self, **kwargs): order = Order.objects.get(pk=kwargs.get('order_id')) context = super(CoinifyView, self).get_context_data(**kwargs) context['order'] = order + ### Initiate coinify API and create invoice coinifyapi = CoinifyAPI(settings.COINIFY_API_KEY, settings.COINIFY_API_SECRET) - response = coinifyapi.invoice_create( amount, currency,