From 2d4e4ba631e4ae4fe5c6e22ffdbcb4cf3e5d0577 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Tue, 20 Jun 2023 10:19:06 -0600 Subject: [PATCH] Add free order checkout process --- .../templates/dashboard/order/detail.html | 6 +- dashboard/views.py | 1 + storefront/cart.py | 2 +- .../templates/storefront/order_form.html | 8 +- .../templates/storefront/payment_done.html | 10 +- storefront/urls.py | 5 + storefront/views.py | 97 ++++++++++++++----- 7 files changed, 97 insertions(+), 32 deletions(-) diff --git a/dashboard/templates/dashboard/order/detail.html b/dashboard/templates/dashboard/order/detail.html index 4ae6747..297b7c3 100644 --- a/dashboard/templates/dashboard/order/detail.html +++ b/dashboard/templates/dashboard/order/detail.html @@ -31,9 +31,9 @@ {% if order.subscription %}
Subscription
- {{ order.subscription_description }} View on Stripe ↗ + {{ order.subscription_description }} View on Stripe ↗
- {% else %} + {% elif order.transaction.paypal_id %}
PayPal Transaction
{{order.transaction.get_status_display}} View on PayPal ↗ @@ -113,7 +113,7 @@ -${{ order.coupon_amount }} {% endif %} - + Shipping: ${{ order.shipping_total }} diff --git a/dashboard/views.py b/dashboard/views.py index 2523604..a529b8e 100644 --- a/dashboard/views.py +++ b/dashboard/views.py @@ -477,6 +477,7 @@ class ProductVariantCreateView( 'visible_in_listings', 'track_inventory', 'stock', + 'order_limit', ] def get_context_data(self, **kwargs): diff --git a/storefront/cart.py b/storefront/cart.py index 6f8f2d8..cdf283e 100644 --- a/storefront/cart.py +++ b/storefront/cart.py @@ -196,7 +196,7 @@ class Cart: self.save() def get_item_by_pk(self, pk): - return next(i for i, v in enumerate(self) if v.variant.pk == pk) + return next((i, v) for i, v in enumerate(self) if v.variant.pk == pk) def update_item_quantity(self, item_index, quantity): self.items[item_index].quantity = quantity diff --git a/storefront/templates/storefront/order_form.html b/storefront/templates/storefront/order_form.html index 2e0534c..765fb85 100644 --- a/storefront/templates/storefront/order_form.html +++ b/storefront/templates/storefront/order_form.html @@ -60,7 +60,7 @@

Order summary

-
+ {% csrf_token %} {{form.as_p}}
@@ -86,7 +86,13 @@ + {% if cart.total_price == 0.00 %} +
+ +
+ {% else %}
+ {% endif %}
{% endblock %} diff --git a/storefront/templates/storefront/payment_done.html b/storefront/templates/storefront/payment_done.html index a87db7d..df047a9 100644 --- a/storefront/templates/storefront/payment_done.html +++ b/storefront/templates/storefront/payment_done.html @@ -1,10 +1,10 @@ {% extends "base.html" %} -{% block head_title %}Payment Success | {% endblock %} +{% block head_title %}Order Success | {% endblock %} {% block content %} -
-

Payment was successful

-

Thank you for your order!

-
+
+

We've received your order

+

Thank you!

+
{% endblock %} diff --git a/storefront/urls.py b/storefront/urls.py index 4608e35..df98118 100644 --- a/storefront/urls.py +++ b/storefront/urls.py @@ -57,6 +57,11 @@ urlpatterns = [ views.OrderCreateView.as_view(), name='order-create' ), + path( + 'checkout/free/', + views.FreeOrderCreateView.as_view(), + name='free-order-create' + ), path( 'done/', views.PaymentDoneView.as_view(), diff --git a/storefront/views.py b/storefront/views.py index 34c3c12..a868c64 100644 --- a/storefront/views.py +++ b/storefront/views.py @@ -46,7 +46,7 @@ from core.models import ( ) from core.forms import ShippingRateForm from core.shipping import get_shipping_cost -from core import OrderStatus, ShippingContainer +from core import OrderStatus, ShippingContainer, TransactionStatus from .forms import ( AddToCartForm, CartItemUpdateForm, OrderCreateForm, @@ -356,29 +356,41 @@ class OrderCreateView(CreateView): cart = Cart(request) + try: + user = User.objects.get( + email=request.session.get('shipping_address').get('email') + ) + except User.DoesNotExist: + user = None + + if user: + variants_ordered = ProductVariant.objects.filter( + pk__in=cart.item_variant_pks, + order_lines__order__customer=user, + order_lines__order__status__in=[ + OrderStatus.UNFULFILLED, + OrderStatus.PARTIALLY_FULFILLED, + OrderStatus.FULFILLED + ] + ).values("id", "order_limit").annotate( + num_ordered=Sum("order_lines__quantity") + ).order_by() + + for variant in variants_ordered: + index, item = cart.get_item_by_pk(variant['id']) + available = variant['order_limit'] - variant['num_ordered'] + new_qty = item.quantity if item.quantity < available else available + if new_qty and new_qty <= 0: + cart.remove_item(index) + else: + cart.update_item_quantity(index, new_qty) + + if len(cart) == 0: + return HttpResponseRedirect( + reverse('storefront:product-list') + ) if cart.coupon is not None: - try: - user = User.objects.get( - email=request.session.get('shipping_address').get('email') - ) - except User.DoesNotExist: - user = None - - if user: - variants_ordered = ProductVariant.objects.filter( - pk__in=cart.item_variant_pks, - order_lines__order__customer=user, - order_lines__order__status="fulfilled" - ).values("id", "order_limit").annotate( - num_ordered=Sum("order_lines__quantity") - ).order_by() - - for item in cart: - if item.quantity - - - if user in cart.coupon.users.all(): cart.remove_coupon() @@ -415,6 +427,47 @@ class OrderCreateView(CreateView): return JsonResponse(data) +class FreeOrderCreateView(CreateView): + http_method_names = ['post'] + model = Order + form_class = OrderCreateForm + success_url = reverse_lazy('storefront:payment-done') + + def form_valid(self, form): + cart = Cart(self.request) + form.instance.subtotal_amount = cart.subtotal_price + form.instance.coupon = cart.coupon + form.instance.coupon_amount = cart.discount_amount + form.instance.total_amount = cart.total_price + form.instance.weight = cart.total_weight + shipping_container = cart.get_shipping_container() + form.instance.shipping_total = cart.get_shipping_price(shipping_container) + shipping_address = self.request.session.get('shipping_address') + form.instance.customer, form.instance.shipping_address = get_or_create_customer(self.request, shipping_address) + form.instance.status = OrderStatus.UNFULFILLED + self.object = form.save() + bulk_list = cart.build_bulk_list(self.object) + OrderLine.objects.bulk_create(bulk_list) + self.object.minus_stock() + + try: + coupon = Coupon.objects.get( + code=self.request.session.get('coupon_code') + ) + except ObjectDoesNotExist: + coupon = None + + if coupon: + self.object.coupon = coupon + coupon.users.add(self.object.customer) + + transaction = Transaction.objects.get(order=self.object) + transaction.status = TransactionStatus.COMPLETED + transaction.save() + cart.clear() + return HttpResponseRedirect(self.get_success_url()) + + @csrf_exempt @require_POST def paypal_order_transaction_capture(request, transaction_id):