Add more variants
This commit is contained in:
parent
34b6eb6bfd
commit
504bc3a146
@ -162,7 +162,7 @@ class ProductVariant(models.Model):
|
||||
return f'{self.product}: {self.name}'
|
||||
|
||||
class Meta:
|
||||
pass
|
||||
ordering = ['weight']
|
||||
|
||||
|
||||
class ProductOption(models.Model):
|
||||
|
||||
@ -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 ↓</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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 %}
|
||||
18
src/dashboard/templates/dashboard/variant_form.html
Normal file
18
src/dashboard/templates/dashboard/variant_form.html
Normal 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 %}
|
||||
@ -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(),
|
||||
|
||||
@ -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']})
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user