aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Lemon <y@yulqen.org>2024-10-19 21:35:20 +0100
committerMatthew Lemon <y@yulqen.org>2024-10-19 21:35:20 +0100
commit9b06fa6596def3505af076d6f8807a251c4162e4 (patch)
tree55f15a16aa4ef00f9050eaefac413933d203c3e3
parent1e1a2f6ac2cadfbc57cc855a67498af097391caf (diff)
Add multiple items to the cart and Stripe process
- Very rough but it works - Multiple items can be added to cart - Can be bought with stripe - Shopping cart is deleted after successful transaction
-rw-r--r--alphabetlearning/payments/admin.py29
-rw-r--r--alphabetlearning/payments/models.py2
-rw-r--r--alphabetlearning/payments/urls.py2
-rw-r--r--alphabetlearning/payments/views.py40
-rw-r--r--alphabetlearning/templates/payments/cart_detail.html3
-rw-r--r--alphabetlearning/templates/payments/cart_sidepanel.html5
-rw-r--r--alphabetlearning/templates/resources/resource_card_featured.html5
-rw-r--r--alphabetlearning/templates/resources/resource_card_standard.html5
8 files changed, 63 insertions, 28 deletions
diff --git a/alphabetlearning/payments/admin.py b/alphabetlearning/payments/admin.py
index 9588f3b..685af63 100644
--- a/alphabetlearning/payments/admin.py
+++ b/alphabetlearning/payments/admin.py
@@ -9,31 +9,36 @@ from .models import SubscriptionPlan
from alphabetlearning.resources.models import Resource
-#class PriceAdmin(admin.ModelAdmin):
-# list_display =
+# class PriceAdmin(admin.ModelAdmin):
+# list_display =
-#class ProductAdmin(admin.ModelAdmin):
+# class ProductAdmin(admin.ModelAdmin):
# inlines = [PriceInlineAdmin]
+
class SubscriptionPlanAdmin(admin.ModelAdmin):
- list_display = ('name', 'price', 'description', 'allowed_downloads')
+ list_display = ("name", "price", "description", "allowed_downloads")
+
+
+class CartItemAdminInline(admin.TabularInline):
+ model = CartItem
class ShoppingCartAdmin(admin.ModelAdmin):
- list_display = ('user', 'created_at', 'updated_at')
+# list_display = ("user", "created_at", "updated_at")
+ inlines = [CartItemAdminInline,]
-class CartItemAdmin(admin.ModelAdmin):
- list_display = ('cart', 'resource', 'quantity', 'added_at')
+# class CartItemAdmin(admin.ModelAdmin):
+# list_display = ('cart', 'resource', 'quantity', 'added_at')
class SubscriptionAdmin(admin.ModelAdmin):
- list_display = ('user', 'is_active', 'start_date', 'end_date')
+ list_display = ("user", "is_active", "start_date", "end_date")
-#admin.site.register(Product, ProductAdmin)
+# admin.site.register(Product, ProductAdmin)
admin.site.register(Price)
-admin.site.register(SubscriptionPlan)
-admin.site.register(ShoppingCart)
+admin.site.register(ShoppingCart, ShoppingCartAdmin)
admin.site.register(CartItem)
-admin.site.register(Subscription)
+admin.site.register(Subscription, SubscriptionAdmin)
diff --git a/alphabetlearning/payments/models.py b/alphabetlearning/payments/models.py
index 0ad07fb..7bf4164 100644
--- a/alphabetlearning/payments/models.py
+++ b/alphabetlearning/payments/models.py
@@ -14,7 +14,7 @@ class Product(models.Model):
class Price(models.Model):
- resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name="price")
+ resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name="price_obj")
price = models.IntegerField(default=0)
stripe_price_id = models.CharField(max_length=100)
diff --git a/alphabetlearning/payments/urls.py b/alphabetlearning/payments/urls.py
index b782bdc..d5b0dd5 100644
--- a/alphabetlearning/payments/urls.py
+++ b/alphabetlearning/payments/urls.py
@@ -16,7 +16,7 @@ urlpatterns = [
views.CreateCheckoutSessionView.as_view(),
name="create-checkout-session",
),
- path("add-to-card/<int:resource_id>", views.add_to_cart, name="add_to_cart"),
+ path("add-to-basket/<int:resource_id>", views.add_to_cart, name="add_to_basket"),
path("landing/", views.ProductLandingPageView.as_view(), name="landing"),
path("webhooks/stripe/", views.stripe_webhook, name="stripe-webhook"),
]
diff --git a/alphabetlearning/payments/views.py b/alphabetlearning/payments/views.py
index 6bcb5a5..dae1a9d 100644
--- a/alphabetlearning/payments/views.py
+++ b/alphabetlearning/payments/views.py
@@ -37,19 +37,23 @@ from .models import ShoppingCart
stripe.api_key = settings.STRIPE_SECRET_KEY
+def create_line_items(resources):
+ price_objs = [r.price_obj.first() for r in resources]
+ stripe_price_ids = [p.stripe_price_id for p in price_objs]
+ return [{"quantity": 1, "price": s} for s in stripe_price_ids]
+ pass
class CreateCheckoutSessionView(View):
def post(self, request, *args, **kwargs):
- price = Price.objects.get(id=self.kwargs["pk"])
+ #price = Price.objects.get(id=self.kwargs["pk"])
+ cart = ShoppingCart.objects.get(id=self.kwargs["pk"])
+ resources = [i.resource for i in cart.items.all()]
+ total = sum([r.price_obj.first().price for r in resources])
domain = "http://localhost:8000"
checkout_session = stripe.checkout.Session.create(
payment_method_types=["card"],
- line_items=[
- {
- "price": price.stripe_price_id,
- "quantity": 1,
- },
- ],
+ customer_email=request.user.email,
+ line_items=create_line_items(resources),
mode="payment",
success_url=domain + "/payments/success/",
cancel_url=domain + "/payments/cancel/",
@@ -83,13 +87,20 @@ def add_to_cart(request, resource_id):
cart_item, created = CartItem.objects.get_or_create(cart=cart, resource=resource)
# cart_item.quantity += 1
cart_item.save()
- return render(request, "payments/cart_detail.html", {"cart": cart})
+ return redirect("payments:cart_detail")
@login_required
def cart_detail(request):
cart, created = ShoppingCart.objects.get_or_create(user=request.user)
- return render(request, "payments/cart_detail.html", {"cart": cart})
+ resources = [i.resource for i in cart.items.all()]
+ total = sum([r.price_obj.first().price for r in resources])
+ context = {
+ "cart": cart,
+ "resources": resources,
+ "total": total
+ }
+ return render(request, "payments/cart_detail.html", context)
# def cart_detail(request):
@@ -135,6 +146,17 @@ def stripe_webhook(request):
customer_email = session["customer_details"]["email"]
payment_intent = session["payment_intent"]
+ # TODO Add the items to the users profile page
+ # This should be done before deleting the cart otherwise we have no record of what they bought
+
+ # TODO clear their shopping cart - we need to obtain their user ID
+ user = User.objects.get(email=customer_email)
+ ShoppingCart.objects.get(user=user).delete()
+ print(f"Deleted cart for {user}")
+
+ # TODO add the transaction to our local history? Or just use Stripe?
+
+
# TODO send an email to the customer
send_mail(
"Thank you for your purchase",
diff --git a/alphabetlearning/templates/payments/cart_detail.html b/alphabetlearning/templates/payments/cart_detail.html
index 8c6c01b..46117d1 100644
--- a/alphabetlearning/templates/payments/cart_detail.html
+++ b/alphabetlearning/templates/payments/cart_detail.html
@@ -21,9 +21,8 @@
</div>
<div class="col-4 my-5">
- {% include "payments/cart_sidepanel.html" with cart=cart %}
+ {% include "payments/cart_sidepanel.html" with cart=cart total=total %}
</div>
-
</div>
{% else %}
<p>Your cart is empty.</p>
diff --git a/alphabetlearning/templates/payments/cart_sidepanel.html b/alphabetlearning/templates/payments/cart_sidepanel.html
index 7742c9a..b788d24 100644
--- a/alphabetlearning/templates/payments/cart_sidepanel.html
+++ b/alphabetlearning/templates/payments/cart_sidepanel.html
@@ -23,6 +23,9 @@
</div>
<div class="d-grid gap-2 mx-auto col-11">
- <button class="btn btn-primary btn-lg">Checkout now</button>
+ <form action="{% url 'payments:create-checkout-session' cart.id %}" method="POST">
+ {% csrf_token %}
+ <button class="btn btn-primary btn-lg">Checkout now</button>
+ </form>
</div>
</div>
diff --git a/alphabetlearning/templates/resources/resource_card_featured.html b/alphabetlearning/templates/resources/resource_card_featured.html
index 8a92729..c83ac0f 100644
--- a/alphabetlearning/templates/resources/resource_card_featured.html
+++ b/alphabetlearning/templates/resources/resource_card_featured.html
@@ -32,7 +32,10 @@
{% endif %}
<div class="d-flex flex-row justify-content-between align-items-end mt-2">
<p class="card-text m-1"><small class="text-muted">1 credit</small></p>
- <button type="button" class="btn btn-success fs-6 px-2 py-0">Add to basket</button>
+ <form action="{% url 'payments:add_to_basket' resource.id %}" method="POST">
+ {% csrf_token %}
+ <button type="submit" class="btn btn-success fs-6 px-2 py-0">Add to basket</button>
+ </form>
</div>
</div>
diff --git a/alphabetlearning/templates/resources/resource_card_standard.html b/alphabetlearning/templates/resources/resource_card_standard.html
index f8a557b..9850117 100644
--- a/alphabetlearning/templates/resources/resource_card_standard.html
+++ b/alphabetlearning/templates/resources/resource_card_standard.html
@@ -37,7 +37,10 @@
</div>
<div class="d-flex flex-row justify-content-between align-items-end mt-2">
<p class="card-text m-1"><small class="text-muted">1 credit</small></p>
- <button type="button" class="btn btn-success fs-6 px-2 py-0">Add to basket</button>
+ <form action="{% url 'payments:add_to_basket' resource.id %}" method="POST">
+ {% csrf_token %}
+ <button type="submit" class="btn btn-success fs-6 px-2 py-0">Add to basket</button>
+ </form>
</div>
</div>
</div>