Merge branch 'feature/free-sample-form' into develop

This commit is contained in:
Nathan Chapman 2023-06-20 10:23:52 -06:00
commit 94b12c9f3a
11 changed files with 141 additions and 17 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.6 on 2023-06-19 23:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='productvariant',
name='max_order_per_customer',
field=models.PositiveIntegerField(blank=True, null=True),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.6 on 2023-06-20 02:59
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('core', '0002_productvariant_max_order_per_customer'),
]
operations = [
migrations.RenameField(
model_name='productvariant',
old_name='max_order_per_customer',
new_name='order_limit',
),
]

View File

@ -192,11 +192,12 @@ class ProductVariant(models.Model):
validators=[MinValueValidator(0)]
)
sorting = models.PositiveIntegerField(blank=True, null=True)
order_limit = models.PositiveIntegerField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = ProductVariantManager()
#objects = ProductVariantManager()
def __str__(self):
return f'{self.product}: {self.name}'

View File

@ -27,6 +27,7 @@ class ProductVariantUpdateForm(forms.ModelForm):
'track_inventory',
'stock',
'sorting',
'order_limit',
'image'
]

View File

@ -33,7 +33,7 @@
<dd>
{{ order.subscription_description }}&emsp;<a href="https://dashboard.stripe.com/subscriptions/{{ order.subscription.stripe_id }}" target="_blank">View on Stripe &nearr;</a>
</dd>
{% else %}
{% elif order.transaction.paypal_id %}
<dt>PayPal Transaction</dt>
<dd>
{{order.transaction.get_status_display}}&emsp;<a href="https://www.paypal.com/activity/payment/{{ order.transaction.paypal_id }}" target="_blank">View on PayPal &nearr;</a>

View File

@ -477,6 +477,7 @@ class ProductVariantCreateView(
'visible_in_listings',
'track_inventory',
'stock',
'order_limit',
]
def get_context_data(self, **kwargs):

View File

@ -195,6 +195,9 @@ class Cart:
self.items.append(new_item)
self.save()
def get_item_by_pk(self, 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
self.save()

View File

@ -60,7 +60,7 @@
</section>
<section class="cart__summary">
<h3>Order summary</h3>
<form action="" method="POST" class="order-create-form">
<form id="order-create-form" action="" method="POST" class="order-create-form">
{% csrf_token %}
{{form.as_p}}
</form>
@ -86,7 +86,13 @@
</tr>
</table>
</div>
{% if cart.total_price == 0.00 %}
<div>
<button type="submit" form="order-create-form" formaction="{% url 'storefront:free-order-create' %}">Place order</button>
</div>
{% else %}
<div id="paypal-button-container"></div>
{% endif %}
</section>
</article>
{% endblock %}

View File

@ -1,10 +1,10 @@
{% extends "base.html" %}
{% block head_title %}Payment Success | {% endblock %}
{% block head_title %}Order Success | {% endblock %}
{% block content %}
<article>
<h1>Payment was successful</h1>
<p>Thank you for your order!</p>
<article class="text-center">
<h1>We've received your order</h1>
<p>Thank you!</p>
</article>
{% endblock %}

View File

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

View File

@ -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,
@ -355,13 +355,43 @@ class OrderCreateView(CreateView):
cart = Cart(request)
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__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:
if user in cart.coupon.users.all():
cart.remove_coupon()
messages.warning(request, 'Coupon already used.')
@ -397,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):