Add more variants

This commit is contained in:
Nathan Chapman 2022-10-08 08:04:51 -06:00
parent 34b6eb6bfd
commit 504bc3a146
13 changed files with 145 additions and 46 deletions

View File

@ -162,7 +162,7 @@ class ProductVariant(models.Model):
return f'{self.product}: {self.name}'
class Meta:
pass
ordering = ['weight']
class ProductOption(models.Model):

View File

@ -6,13 +6,7 @@
<header class="object__header">
<h1><img src="{% static 'images/box.png' %}" alt=""> Order #{{order.pk}}</h1>
<div class="object__menu">
<div class="dropdown">
<span class="dropdown__menu">Options &darr;</span>
<div class="dropdown__child">
<a href="{% url 'dashboard:order-cancel' order.pk %}">Cancel order</a>
<a href="">Return order</a>
</div>
</div>
<a class="action-button action-button--warning" href="{% url 'dashboard:order-cancel' order.pk %}">Cancel order</a>
<span class="order__status order__status--{{order.status}}">{{order.get_status_display}} ({{order.total_quantity_fulfilled}} / {{order.total_quantity_ordered}})</span>
</div>
</header>
@ -33,7 +27,7 @@
</figure>
<span>{{product.sku}}</span>
<span>{{item.quantity}}</span>
<span>${{product.price}}</span>
<span>${{item.variant.price}}</span>
<span>${{item.get_total}}</span>
{% endwith %}
</div>

View File

@ -7,7 +7,6 @@
<form method="POST" action="">
{% csrf_token %}
{{ form.management_form }}
<section class="object__list">
{% for dict in form.errors %}
{% for error in dict.values %}
@ -20,15 +19,15 @@
<span>Product</span>
<span>SKU</span>
<span>Quantity to fulfill</span>
<span>Grind</span>
<span>Options</span>
</div>
{% for form in form %}
<div class="object__item object__item--col4">
{% with product=form.instance.product %}
{% with product=form.instance.variant.product %}
{{form.id}}
<figure class="item__figure">
<img class="product__image product__image--small" src="{{product.get_first_img.image.url}}" alt="{{product.get_first_img.image}}">
<figcaption><strong>{{product.name}}</strong></figcaption>
<figcaption><strong>{{form.instance.variant}}</strong></figcaption>
</figure>
<span>{{product.sku}}</span>
<span>{{form.quantity_fulfilled}} / {{form.instance.quantity}}</span>

View File

@ -32,13 +32,14 @@
</div>
{% for variant in product.variants.all %}
<div class="panel__item">
<p>name: {{ variant.name }}</p>
<p>sku: {{ variant.sku }}</p>
<p>stripe_id: {{ variant.stripe_id }}</p>
<p>price: ${{ variant.price }}</p>
<p>weight: {{ variant.weight }}</p>
<p>track_inventory: {{ variant.track_inventory }}</p>
<p>stock: {{ variant.stock }}</p>
<h3>{{ variant.name }}</h3>
<p>SKU: {{ variant.sku }}</p>
<p>Price: ${{ variant.price }}</p>
<p>Weight: {{ variant.weight }}</p>
{% if variant.track_inventory %}
<p>Stock: {{ variant.stock }}</p>
{% endif %}
<p><a href="{% url 'dashboard:variant-update' product.pk variant.pk %}">Edit</a></p>
</div>
{% endfor %}
</section>

View File

@ -0,0 +1,20 @@
{% extends "dashboard.html" %}
{% load static %}
{% block content %}
<article>
<header class="object__header">
<h1>Delete Variant</h1>
</header>
<section class="variant__detail object__panel">
<form method="post" class="panel__item">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
{{ form.as_p }}
<p>
<input class="action-button action-button--warning" type="submit" value="Confirm"> or <a href="{% url 'dashboard:product-detail' product.pk %}">cancel</a>
</p>
</form>
</section>
</article>
{% endblock content %}

View File

@ -0,0 +1,18 @@
{% extends "dashboard.html" %}
{% block content %}
<article class="product">
<header class="object__header">
<h1>Update variant</h1>
</header>
<section class="object__panel">
<form class="panel__item" method="POST" action="{% url 'dashboard:variant-update' product.pk variant.pk %}">
{% csrf_token %}
{{form.as_p}}
<p class="form__submit">
<input class="action-button" type="submit" value="Create variant"> or <a href="{% url 'dashboard:product-detail' product.pk %}">cancel</a>
</p>
</form>
</section>
</article>
{% endblock %}

View File

@ -130,11 +130,6 @@ urlpatterns = [
name='variant-create'
),
path('<int:variant_pk>/', include([
path(
'',
views.ProductVariantDetailView.as_view(),
name='variant-detail'
),
path(
'update/',
views.ProductVariantUpdateView.as_view(),

View File

@ -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']})

View File

@ -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
)

View File

@ -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