From 504bc3a1463f4f61d3d72770824501c91a814a05 Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Sat, 8 Oct 2022 08:04:51 -0600 Subject: [PATCH] Add more variants --- src/core/models.py | 2 +- .../templates/dashboard/order_detail.html | 10 +--- .../templates/dashboard/order_fulfill.html | 7 ++- .../templates/dashboard/product_detail.html | 15 +++--- .../dashboard/productvariant_detail.html | 0 .../dashboard/productvariant_form.html | 0 .../dashboard/variant_confirm_delete.html | 20 +++++++ ...ate_form.html => variant_create_form.html} | 0 .../templates/dashboard/variant_form.html | 18 +++++++ src/dashboard/urls.py | 5 -- src/dashboard/views.py | 53 +++++++++++++++---- src/ptcoffee/settings.py | 26 ++++----- src/storefront/cart.py | 35 ++++++++++++ 13 files changed, 145 insertions(+), 46 deletions(-) delete mode 100644 src/dashboard/templates/dashboard/productvariant_detail.html delete mode 100644 src/dashboard/templates/dashboard/productvariant_form.html create mode 100644 src/dashboard/templates/dashboard/variant_confirm_delete.html rename src/dashboard/templates/dashboard/{productvariant_create_form.html => variant_create_form.html} (100%) create mode 100644 src/dashboard/templates/dashboard/variant_form.html diff --git a/src/core/models.py b/src/core/models.py index aeff19c..69dc9ef 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -162,7 +162,7 @@ class ProductVariant(models.Model): return f'{self.product}: {self.name}' class Meta: - pass + ordering = ['weight'] class ProductOption(models.Model): diff --git a/src/dashboard/templates/dashboard/order_detail.html b/src/dashboard/templates/dashboard/order_detail.html index a457290..0c325b8 100644 --- a/src/dashboard/templates/dashboard/order_detail.html +++ b/src/dashboard/templates/dashboard/order_detail.html @@ -6,13 +6,7 @@

Order #{{order.pk}}

- + Cancel order {{order.get_status_display}} ({{order.total_quantity_fulfilled}} / {{order.total_quantity_ordered}})
@@ -33,7 +27,7 @@ {{product.sku}} {{item.quantity}} - ${{product.price}} + ${{item.variant.price}} ${{item.get_total}} {% endwith %} diff --git a/src/dashboard/templates/dashboard/order_fulfill.html b/src/dashboard/templates/dashboard/order_fulfill.html index 2e7b351..339947d 100644 --- a/src/dashboard/templates/dashboard/order_fulfill.html +++ b/src/dashboard/templates/dashboard/order_fulfill.html @@ -7,7 +7,6 @@
{% csrf_token %} {{ form.management_form }} -
{% for dict in form.errors %} {% for error in dict.values %} @@ -20,15 +19,15 @@ Product SKU Quantity to fulfill - Grind + Options {% for form in form %}
- {% with product=form.instance.product %} + {% with product=form.instance.variant.product %} {{form.id}}
{{product.get_first_img.image}} -
{{product.name}}
+
{{form.instance.variant}}
{{product.sku}} {{form.quantity_fulfilled}} / {{form.instance.quantity}} diff --git a/src/dashboard/templates/dashboard/product_detail.html b/src/dashboard/templates/dashboard/product_detail.html index e8a2ce5..6bb34f3 100644 --- a/src/dashboard/templates/dashboard/product_detail.html +++ b/src/dashboard/templates/dashboard/product_detail.html @@ -32,13 +32,14 @@
{% for variant in product.variants.all %}
-

name: {{ variant.name }}

-

sku: {{ variant.sku }}

-

stripe_id: {{ variant.stripe_id }}

-

price: ${{ variant.price }}

-

weight: {{ variant.weight }}

-

track_inventory: {{ variant.track_inventory }}

-

stock: {{ variant.stock }}

+

{{ variant.name }}

+

SKU: {{ variant.sku }}

+

Price: ${{ variant.price }}

+

Weight: {{ variant.weight }}

+ {% if variant.track_inventory %} +

Stock: {{ variant.stock }}

+ {% endif %} +

Edit

{% endfor %}
diff --git a/src/dashboard/templates/dashboard/productvariant_detail.html b/src/dashboard/templates/dashboard/productvariant_detail.html deleted file mode 100644 index e69de29..0000000 diff --git a/src/dashboard/templates/dashboard/productvariant_form.html b/src/dashboard/templates/dashboard/productvariant_form.html deleted file mode 100644 index e69de29..0000000 diff --git a/src/dashboard/templates/dashboard/variant_confirm_delete.html b/src/dashboard/templates/dashboard/variant_confirm_delete.html new file mode 100644 index 0000000..365b892 --- /dev/null +++ b/src/dashboard/templates/dashboard/variant_confirm_delete.html @@ -0,0 +1,20 @@ +{% extends "dashboard.html" %} +{% load static %} + +{% block content %} +
+
+

Delete Variant

+
+
+ + {% csrf_token %} +

Are you sure you want to delete "{{ object }}"?

+ {{ form.as_p }} +

+ or cancel +

+ +
+
+{% endblock content %} diff --git a/src/dashboard/templates/dashboard/productvariant_create_form.html b/src/dashboard/templates/dashboard/variant_create_form.html similarity index 100% rename from src/dashboard/templates/dashboard/productvariant_create_form.html rename to src/dashboard/templates/dashboard/variant_create_form.html diff --git a/src/dashboard/templates/dashboard/variant_form.html b/src/dashboard/templates/dashboard/variant_form.html new file mode 100644 index 0000000..85ad698 --- /dev/null +++ b/src/dashboard/templates/dashboard/variant_form.html @@ -0,0 +1,18 @@ +{% extends "dashboard.html" %} + +{% block content %} +
+
+

Update variant

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

+ or cancel +

+
+
+
+{% endblock %} diff --git a/src/dashboard/urls.py b/src/dashboard/urls.py index 2fc3d1f..4fde679 100644 --- a/src/dashboard/urls.py +++ b/src/dashboard/urls.py @@ -130,11 +130,6 @@ urlpatterns = [ name='variant-create' ), path('/', include([ - path( - '', - views.ProductVariantDetailView.as_view(), - name='variant-detail' - ), path( 'update/', views.ProductVariantUpdateView.as_view(), diff --git a/src/dashboard/views.py b/src/dashboard/views.py index 4d23580..93f3ecc 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -239,6 +239,20 @@ class ProductDetailView(LoginRequiredMixin, DetailView): model = Product template_name = 'dashboard/product_detail.html' + def get_object(self): + pk = self.kwargs.get(self.pk_url_kwarg) + queryset = Product.objects.filter( + pk=pk + ).select_related( + 'category', + ).prefetch_related( + 'variants', + 'options', + 'productphoto_set' + ) + obj = queryset.get() + return obj + class ProductUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView): model = Product @@ -293,8 +307,8 @@ class ProductPhotoDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView class ProductVariantCreateView(SuccessMessageMixin, CreateView): model = ProductVariant - success_message = 'ProductVariant created.' - template_name = 'dashboard/productvariant_create_form.html' + success_message = 'Variant created.' + template_name = 'dashboard/variant_create_form.html' fields = [ 'name', 'sku', @@ -303,7 +317,6 @@ class ProductVariantCreateView(SuccessMessageMixin, CreateView): 'track_inventory', 'stock', ] - success_message = 'Variant created.' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -318,22 +331,44 @@ class ProductVariantCreateView(SuccessMessageMixin, CreateView): return reverse('dashboard:product-detail', kwargs={'pk': self.kwargs['pk']}) -class ProductVariantDetailView(DetailView): - model = ProductVariant - pk_url_kwarg = 'variant_pk' - - class ProductVariantUpdateView(SuccessMessageMixin, UpdateView): model = ProductVariant pk_url_kwarg = 'variant_pk' success_message = 'ProductVariant saved.' - fields = '__all__' + template_name = 'dashboard/variant_form.html' + fields = [ + 'name', + 'sku', + 'price', + 'weight', + 'track_inventory', + 'stock', + ] + context_object_name = 'variant' + + 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) + + def get_success_url(self): + return reverse('dashboard:product-detail', kwargs={'pk': self.kwargs['pk']}) class ProductVariantDeleteView(SuccessMessageMixin, DeleteView): model = ProductVariant pk_url_kwarg = 'variant_pk' success_message = 'ProductVariant deleted.' + template_name = 'dashboard/variant_confirm_delete.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['product'] = Product.objects.get(pk=self.kwargs['pk']) + return context def get_success_url(self): return reverse('dashboard:product-detail', kwargs={'pk': self.kwargs['pk']}) diff --git a/src/ptcoffee/settings.py b/src/ptcoffee/settings.py index f92ac4e..45c79c0 100644 --- a/src/ptcoffee/settings.py +++ b/src/ptcoffee/settings.py @@ -257,17 +257,19 @@ CELERY_TASK_TRACK_STARTED = True CELERY_TIMEZONE = 'US/Mountain' # Sentry -sentry_sdk.init( - dsn=SENTRY_DSN, - environment=SENTRY_ENV, - integrations=[DjangoIntegration()], - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for performance monitoring. - # We recommend adjusting this value in production. - traces_sample_rate=1.0, +if not DEBUG: + sentry_sdk.init( + dsn=SENTRY_DSN, + environment=SENTRY_ENV, + integrations=[DjangoIntegration()], - # If you wish to associate users to errors (assuming you are using - # django.contrib.auth) you may enable sending PII data. - send_default_pii=True -) + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for performance monitoring. + # We recommend adjusting this value in production. + traces_sample_rate=1.0, + + # If you wish to associate users to errors (assuming you are using + # django.contrib.auth) you may enable sending PII data. + send_default_pii=True + ) diff --git a/src/storefront/cart.py b/src/storefront/cart.py index 633453a..716eb68 100644 --- a/src/storefront/cart.py +++ b/src/storefront/cart.py @@ -23,12 +23,47 @@ from core import ( build_usps_rate_request ) +from .forms import UpdateCartItemForm from .payments import CreateOrder logger = logging.getLogger(__name__) +class CartItem: + update_form = UpdateCartItemForm + + def __init__(self, item): + self.variant = item['variant'] + self.quantity = item['quantity'] + self.options = item['options'] + + def get_update_form(self, index): + return self.update_form(initial={ + 'item_pk': index, + 'quantity': self.quantity + }) + + def build_paypal_dict(self): + return { + # Shows within upper-right dropdown during payment approval + "name": str(self.variant), + # Item details will also be in the completed paypal.com + # transaction view + "description": self.variant.product.subtitle, + "unit_amount": { + "currency_code": settings.DEFAULT_CURRENCY, + "value": f'{self.variant.price}', + }, + "quantity": f'{item["quantity"]}', + } + + def __str__(self): + return str(self.variant) + + class Cart: + item_class = CartItem + def __init__(self, request): self.request = request self.session = request.session