From 481575e968106c6bae2d112c313972a2c6da9e26 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Sat, 22 Oct 2022 09:09:12 -0600 Subject: [PATCH 1/4] Add form --- .../templates/dashboard/option_form.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/dashboard/templates/dashboard/option_form.html b/src/dashboard/templates/dashboard/option_form.html index e69de29..84f5538 100644 --- a/src/dashboard/templates/dashboard/option_form.html +++ b/src/dashboard/templates/dashboard/option_form.html @@ -0,0 +1,18 @@ +{% extends "dashboard.html" %} + +{% block content %} +
+
+

Update option

+
+
+
+ {% csrf_token %} + {{form.as_p}} +

+ or cancel +

+
+
+
+{% endblock %} From 11d3b740aa2ed3b0b21caad3d5897f125666bb18 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Wed, 26 Oct 2022 09:29:51 -0600 Subject: [PATCH 2/4] Add basic stock handling --- src/core/models.py | 18 +++++++++++++++ .../templates/dashboard/variant_form.html | 2 +- src/dashboard/views.py | 5 ++++ .../templates/storefront/category_detail.html | 1 - src/storefront/views.py | 23 +++++++++++++++---- 5 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/core/models.py b/src/core/models.py index d4de40b..2962905 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -366,6 +366,14 @@ class Order(models.Model): objects = OrderManager() + def minus_stock(self): + for line in self.lines.all(): + line.minus_stock() + + def add_stock(self): + for line in self.lines.all(): + line.add_stock() + def get_total_quantity(self): return sum([line.quantity for line in self]) @@ -443,6 +451,16 @@ class OrderLine(models.Model): def quantity_unfulfilled(self): return self.quantity - self.quantity_fulfilled + def minus_stock(self): + if self.variant.track_inventory: + self.variant.stock -= self.quantity + self.variant.save() + + def add_stock(self): + if self.variant.track_inventory: + self.variant.stock += self.quantity + self.variant.save() + class TrackingNumber(models.Model): order = models.ForeignKey( diff --git a/src/dashboard/templates/dashboard/variant_form.html b/src/dashboard/templates/dashboard/variant_form.html index 03f496e..44107d8 100644 --- a/src/dashboard/templates/dashboard/variant_form.html +++ b/src/dashboard/templates/dashboard/variant_form.html @@ -11,7 +11,7 @@ {% csrf_token %} {{form.as_p}}

- or cancel + or cancel

diff --git a/src/dashboard/views.py b/src/dashboard/views.py index 1da356a..de64a44 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -234,6 +234,11 @@ class OrderCancelView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): 'status': OrderStatus.CANCELED } + def form_valid(self, form): + form.instance.add_stock() + form.instance.save() + return super().form_valid(form) + def get_success_url(self): return reverse('dashboard:order-detail', kwargs={'pk': self.object.pk}) diff --git a/src/storefront/templates/storefront/category_detail.html b/src/storefront/templates/storefront/category_detail.html index 1ab698e..c19c4fb 100644 --- a/src/storefront/templates/storefront/category_detail.html +++ b/src/storefront/templates/storefront/category_detail.html @@ -10,7 +10,6 @@

Welcome to our new website!

NEW COOL LOOK, SAME GREAT COFFEE

-{# Home > Category > "Coffee/Merchandise" #}
{% endblock content %} diff --git a/src/dashboard/templates/dashboard/stock.html b/src/dashboard/templates/dashboard/stock.html new file mode 100644 index 0000000..fe545ed --- /dev/null +++ b/src/dashboard/templates/dashboard/stock.html @@ -0,0 +1,25 @@ +{% extends "dashboard.html" %} +{% load static %} + +{% block content %} +
+
+

Stock

+
+ +
+
+

Products

+
+
+ {% for variant in variant_list %} +
+

{{ variant }}

+

Variant ID: {{ variant.pk }}

+

Total in warehouse: {{ variant.stock }}

+
+ {% endfor %} +
+
+
+{% endblock %} diff --git a/src/dashboard/urls.py b/src/dashboard/urls.py index b054de5..c2b6fdf 100644 --- a/src/dashboard/urls.py +++ b/src/dashboard/urls.py @@ -17,6 +17,11 @@ urlpatterns = [ views.CatalogView.as_view(), name='catalog' ), + path( + 'stock/', + views.StockView.as_view(), + name='stock' + ), path( 'shipping-rates/new/', diff --git a/src/dashboard/views.py b/src/dashboard/views.py index de64a44..7e5814e 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -101,6 +101,20 @@ class CatalogView(ListView): return context +class StockView(ListView): + model = ProductVariant + context_object_name = 'variant_list' + template_name = 'dashboard/stock.html' + + def get_queryset(self): + object_list = ProductVariant.objects.filter( + track_inventory=True + ).order_by('product') + # quantity + # quantity_fulfilled + return object_list + + class ShippingRateDetailView(LoginRequiredMixin, DetailView): model = ShippingRate context_object_name = 'rate' @@ -487,6 +501,7 @@ class ProductOptionDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteVie class CustomerListView(LoginRequiredMixin, ListView): model = User template_name = 'dashboard/customer_list.html' + paginate_by = 100 def get_queryset(self): object_list = User.objects.filter( diff --git a/src/static/images/warehouse.png b/src/static/images/warehouse.png new file mode 100644 index 0000000000000000000000000000000000000000..bbede2846489fdd774149262167c94c8119b5820 GIT binary patch literal 5123 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 literal 0 HcmV?d00001 diff --git a/src/storefront/cart.py b/src/storefront/cart.py index 65d0f28..8e6d381 100644 --- a/src/storefront/cart.py +++ b/src/storefront/cart.py @@ -72,7 +72,7 @@ class Cart: if update_quantity: self.cart[item['variant']]['quantity'] = item['quantity'] else: - self.cart.append(item) + self.add_or_update_item(item) # TODO: abstract this to a function that will check the max amount of item in the cart if len(self) <= 20: @@ -80,6 +80,17 @@ class Cart: else: messages.warning(request, "Cart is full: 20 items or less.") + def add_or_update_item(self, new_item): + new_item_pk = int(new_item['variant']) + for item in self: + if new_item_pk == item['variant'].pk: + if new_item['options'] == item['options']: + item['quantity'] += new_item['quantity'] + return + else: + continue + self.cart.append(new_item) + def save(self): self.session[settings.CART_SESSION_ID] = self.cart self.session.modified = True @@ -123,6 +134,9 @@ class Cart: return 0 def get_shipping_container_choices(self): + is_selectable = Q( + is_selectable=True + ) min_weight_matched = Q( min_order_weight__lte=self.get_total_weight()) | Q( min_order_weight__isnull=True @@ -132,7 +146,7 @@ class Cart: max_order_weight__isnull=True ) containers = ShippingRate.objects.filter( - min_weight_matched & max_weight_matched + is_selectable & min_weight_matched & max_weight_matched ) return containers diff --git a/src/storefront/views.py b/src/storefront/views.py index 5994b41..a332159 100644 --- a/src/storefront/views.py +++ b/src/storefront/views.py @@ -7,6 +7,7 @@ from django.utils import timezone from django.shortcuts import render, reverse, redirect, get_object_or_404 from django.urls import reverse_lazy from django.core.mail import EmailMessage +from django.core.cache import cache from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.http import JsonResponse, HttpResponseRedirect from django.views.generic.base import View, RedirectView, TemplateView @@ -36,7 +37,8 @@ from accounts.forms import ( ) from core.models import ( ProductCategory, Product, ProductVariant, ProductOption, - Order, Transaction, OrderLine, Coupon, ShippingRate + Order, Transaction, OrderLine, Coupon, ShippingRate, + SiteSettings ) from core.forms import ShippingRateForm from core import OrderStatus, ShippingContainer @@ -222,7 +224,7 @@ class CheckoutAddressView(FormView): if user.is_authenticated and user.default_shipping_address: address = user.default_shipping_address initial = { - 'full_name': address.first_name+' '+address.last_name, + 'full_name': address.first_name + ' ' + address.last_name, 'email': user.email, 'street_address_1': address.street_address_1, 'street_address_2': address.street_address_2, @@ -233,7 +235,7 @@ class CheckoutAddressView(FormView): elif self.request.session.get('shipping_address'): address = self.request.session.get('shipping_address') initial = { - 'full_name': address['first_name']+' '+address['last_name'], + 'full_name': address['first_name'] + ' ' + address['last_name'], 'email': address['email'], 'street_address_1': address['street_address_1'], 'street_address_2': address['street_address_2'], @@ -267,6 +269,13 @@ class CheckoutShippingView(FormView): template_name = 'storefront/checkout_shipping_form.html' form_class = CheckoutShippingForm success_url = reverse_lazy('storefront:order-create') + containers = None + + def get_containers(self, request): + if self.containers is None: + cart = Cart(request) + self.containers = cart.get_shipping_container_choices() + return self.containers def get(self, request, *args, **kwargs): if not self.request.session.get('shipping_address'): @@ -274,16 +283,22 @@ class CheckoutShippingView(FormView): return HttpResponseRedirect( reverse('storefront:checkout-address') ) + site_settings = cache.get('SiteSettings') + cart = Cart(self.request) + if len(self.get_containers(request)) == 0: + self.request.session['shipping_container'] = site_settings.default_shipping_rate + return HttpResponseRedirect( + reverse('storefront:order-create') + ) return super().get(request, *args, **kwargs) def get_form(self, form_class=None): cart = Cart(self.request) - containers = cart.get_shipping_container_choices() - for container in containers: + for container in self.get_containers(self.request): container.s_cost = cart.get_shipping_cost(container.container) if form_class is None: form_class = self.get_form_class() - return form_class(containers, **self.get_form_kwargs()) + return form_class(self.get_containers(self.request), **self.get_form_kwargs()) def form_valid(self, form): shipping_container = ShippingRate.objects.get( @@ -400,7 +415,6 @@ def paypal_order_transaction_capture(request, transaction_id): transaction.save() cart.clear() logger.debug(f'\nPayPal Response data: {data}\n') - return JsonResponse(data) else: return JsonResponse({'details': 'invalid request'}) diff --git a/src/templates/dashboard.html b/src/templates/dashboard.html index 690da0b..6409bb3 100644 --- a/src/templates/dashboard.html +++ b/src/templates/dashboard.html @@ -33,6 +33,12 @@ Catalog + Orders From 0e1f32d5b9fba54329d0100d8edf21206909be92 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Sat, 29 Oct 2022 22:53:32 -0600 Subject: [PATCH 4/4] Finalize stock feature --- .../templates/dashboard/order_detail.html | 7 ++- .../templates/dashboard/rate_form.html | 2 +- src/dashboard/templates/dashboard/stock.html | 31 ++++++++----- .../templates/dashboard/variant_restock.html | 19 ++++++++ src/dashboard/urls.py | 5 ++ src/dashboard/views.py | 46 +++++++++++++++++-- src/storefront/cart.py | 18 +++++--- src/storefront/forms.py | 2 +- .../templates/storefront/order_detail.html | 2 +- src/storefront/views.py | 5 ++ src/templates/dashboard.html | 2 - 11 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 src/dashboard/templates/dashboard/variant_restock.html diff --git a/src/dashboard/templates/dashboard/order_detail.html b/src/dashboard/templates/dashboard/order_detail.html index 0c325b8..c530b70 100644 --- a/src/dashboard/templates/dashboard/order_detail.html +++ b/src/dashboard/templates/dashboard/order_detail.html @@ -4,7 +4,10 @@ {% block content %}
-

Order #{{order.pk}}

+
+

Order #{{order.pk}}

+

Date: {{ order.created_at }}

+
Cancel order {{order.get_status_display}} ({{order.total_quantity_fulfilled}} / {{order.total_quantity_ordered}}) @@ -102,7 +105,7 @@ Discount: {{order.coupon.discount_value}} {{order.coupon.get_discount_value_type_display}}
{% endif %} Shipping: ${{order.shipping_total}}
- Total: ${{order.get_total_price_after_discount}} + Total: ${{order.total_amount}}

diff --git a/src/dashboard/templates/dashboard/rate_form.html b/src/dashboard/templates/dashboard/rate_form.html index 81e364e..0947361 100644 --- a/src/dashboard/templates/dashboard/rate_form.html +++ b/src/dashboard/templates/dashboard/rate_form.html @@ -10,7 +10,7 @@ {% csrf_token %} {{form.as_p}}

- or cancel + or cancel

diff --git a/src/dashboard/templates/dashboard/stock.html b/src/dashboard/templates/dashboard/stock.html index fe545ed..b846316 100644 --- a/src/dashboard/templates/dashboard/stock.html +++ b/src/dashboard/templates/dashboard/stock.html @@ -5,21 +5,30 @@

Stock

+

Total in warehouse = available stock + unfulfilled

-
-
-

Products

+
+
+ Product + SKU + Available Stock + Total in warehouse
-
- {% for variant in variant_list %} -
-

{{ variant }}

-

Variant ID: {{ variant.pk }}

-

Total in warehouse: {{ variant.stock }}

-
- {% endfor %} + {% for variant in variant_list %} +
+ {% with product=variant.product %} +
+ {{product.get_first_img.image}} +
{{variant}}
+
+ {{ variant.sku }} + {{ variant.stock }} + {{ variant.total_in_warehouse }} + Restock → + {% endwith %}
+ {% endfor %}
{% endblock %} diff --git a/src/dashboard/templates/dashboard/variant_restock.html b/src/dashboard/templates/dashboard/variant_restock.html new file mode 100644 index 0000000..c75f805 --- /dev/null +++ b/src/dashboard/templates/dashboard/variant_restock.html @@ -0,0 +1,19 @@ +{% extends "dashboard.html" %} + +{% block content %} +
+
+

Restock variant

+
+
+
+ {% csrf_token %} + {{form.as_p}} +

Total in warehouse: {{ variant.total_in_warehouse }}

+

+ or cancel +

+
+
+
+{% endblock %} diff --git a/src/dashboard/urls.py b/src/dashboard/urls.py index c2b6fdf..dc2d70c 100644 --- a/src/dashboard/urls.py +++ b/src/dashboard/urls.py @@ -191,6 +191,11 @@ urlpatterns = [ views.ProductVariantDeleteView.as_view(), name='variant-delete' ), + path( + 'restock/', + views.ProductVariantStockUpdateView.as_view(), + name='variant-restock' + ), ])), ])), ])), diff --git a/src/dashboard/views.py b/src/dashboard/views.py index 7e5814e..1ceb8cd 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -18,7 +18,8 @@ from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.db.models import ( - Exists, OuterRef, Prefetch, Subquery, Count, Sum, Avg, F, Q, Value + Exists, OuterRef, Prefetch, Subquery, Count, Sum, Avg, F, Q, Value, + ExpressionWrapper, IntegerField ) from django.db.models.functions import Coalesce @@ -109,9 +110,14 @@ class StockView(ListView): def get_queryset(self): object_list = ProductVariant.objects.filter( track_inventory=True + ).prefetch_related('order_lines', 'product').annotate( + total_in_warehouse=F('stock') + Coalesce(Sum('order_lines__quantity', filter=Q( + order_lines__order__status=OrderStatus.UNFULFILLED) | Q( + order_lines__order__status=OrderStatus.PARTIALLY_FULFILLED) + ) - Sum('order_lines__quantity_fulfilled', filter=Q( + order_lines__order__status=OrderStatus.UNFULFILLED) | Q( + order_lines__order__status=OrderStatus.PARTIALLY_FULFILLED)), 0) ).order_by('product') - # quantity - # quantity_fulfilled return object_list @@ -460,6 +466,38 @@ class ProductVariantDeleteView(SuccessMessageMixin, DeleteView): return reverse('dashboard:product-detail', kwargs={'pk': self.kwargs['pk']}) +class ProductVariantStockUpdateView(LoginRequiredMixin, UpdateView): + model = ProductVariant + pk_url_kwarg = 'variant_pk' + success_message = 'ProductVariant saved.' + success_url = reverse_lazy('dashboard:stock') + template_name = 'dashboard/variant_restock.html' + fields = [ + 'stock', + ] + context_object_name = 'variant' + + def get_queryset(self): + queryset = ProductVariant.objects.annotate( + total_in_warehouse=F('stock') + Coalesce(Sum('order_lines__quantity', filter=Q( + order_lines__order__status=OrderStatus.UNFULFILLED) | Q( + order_lines__order__status=OrderStatus.PARTIALLY_FULFILLED) + ) - Sum('order_lines__quantity_fulfilled', filter=Q( + order_lines__order__status=OrderStatus.UNFULFILLED) | Q( + order_lines__order__status=OrderStatus.PARTIALLY_FULFILLED)), 0) + ).prefetch_related('order_lines', 'product') + return queryset + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['product'] = Product.objects.get(pk=self.kwargs['pk']) + return context + + def form_valid(self, form): + form.instance.product = Product.objects.get(pk=self.kwargs['pk']) + return super().form_valid(form) + + class ProductOptionDetailView(LoginRequiredMixin, DetailView): model = ProductOption template_name = 'dashboard/option_detail.html' @@ -512,7 +550,7 @@ class CustomerListView(LoginRequiredMixin, ListView): 'orders' ).annotate( num_orders=Count('orders') - ) + ).order_by('first_name', 'last_name') return object_list diff --git a/src/storefront/cart.py b/src/storefront/cart.py index 8e6d381..ff0c03e 100644 --- a/src/storefront/cart.py +++ b/src/storefront/cart.py @@ -76,6 +76,7 @@ class Cart: # TODO: abstract this to a function that will check the max amount of item in the cart if len(self) <= 20: + self.check_item_stock_quantities(request) self.save() else: messages.warning(request, "Cart is full: 20 items or less.") @@ -96,6 +97,14 @@ class Cart: self.session.modified = True logger.info(f'\nCart:\n{self.cart}\n') + def check_item_stock_quantities(self, request): + for item in self: + if item['variant'].track_inventory: + if item['quantity'] > item['variant'].stock: + messages.warning(request, 'Quantity added exceeds available stock.') + item['quantity'] = item['variant'].stock + self.save() + def remove(self, pk): self.cart.pop(pk) self.save() @@ -160,10 +169,7 @@ class Cart: container, str(self.session.get('shipping_address')['postal_code']) ) - try: - logger.info('wafd') - except TypeError as e: - return Decimal('0.00') + usps = USPSApi(settings.USPS_USER_ID, test=True) try: @@ -173,12 +179,12 @@ class Cart: 'Could not connect to USPS, try again.' ) - logger.error(validation.result) + logger.info(validation.result) package = dict(validation.result['RateV4Response']['Package']) if 'Error' not in package: rate = package['Postage']['CommercialRate'] else: - logger.error("USPS Rate error") + logger.error('USPS Rate error') rate = '0.00' return Decimal(rate) else: diff --git a/src/storefront/forms.py b/src/storefront/forms.py index 940fced..fbe7a1c 100644 --- a/src/storefront/forms.py +++ b/src/storefront/forms.py @@ -11,7 +11,7 @@ from localflavor.us.us_states import USPS_CHOICES from usps import USPSApi, Address from captcha.fields import CaptchaField -from core.models import Order +from core.models import Order, ProductVariant from core import CoffeeGrind, ShippingContainer logger = logging.getLogger(__name__) diff --git a/src/storefront/templates/storefront/order_detail.html b/src/storefront/templates/storefront/order_detail.html index d5eb3ca..3ee8ba9 100644 --- a/src/storefront/templates/storefront/order_detail.html +++ b/src/storefront/templates/storefront/order_detail.html @@ -62,7 +62,7 @@ Total - ${{order.get_total_price_after_discount}} + ${{order.total_amount}} diff --git a/src/storefront/views.py b/src/storefront/views.py index a332159..7e46c41 100644 --- a/src/storefront/views.py +++ b/src/storefront/views.py @@ -290,6 +290,11 @@ class CheckoutShippingView(FormView): return HttpResponseRedirect( reverse('storefront:order-create') ) + elif len(self.get_containers(request)) == 1: + self.request.session['shipping_container'] = self.get_containers(request)[0] + return HttpResponseRedirect( + reverse('storefront:order-create') + ) return super().get(request, *args, **kwargs) def get_form(self, form_class=None): diff --git a/src/templates/dashboard.html b/src/templates/dashboard.html index 6409bb3..0f6734a 100644 --- a/src/templates/dashboard.html +++ b/src/templates/dashboard.html @@ -33,12 +33,10 @@ Catalog - Orders