diff options
author | Matthew Lemon <y@yulqen.org> | 2024-10-19 21:35:20 +0100 |
---|---|---|
committer | Matthew Lemon <y@yulqen.org> | 2024-10-19 21:35:20 +0100 |
commit | 9b06fa6596def3505af076d6f8807a251c4162e4 (patch) | |
tree | 55f15a16aa4ef00f9050eaefac413933d203c3e3 | |
parent | 1e1a2f6ac2cadfbc57cc855a67498af097391caf (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.py | 29 | ||||
-rw-r--r-- | alphabetlearning/payments/models.py | 2 | ||||
-rw-r--r-- | alphabetlearning/payments/urls.py | 2 | ||||
-rw-r--r-- | alphabetlearning/payments/views.py | 40 | ||||
-rw-r--r-- | alphabetlearning/templates/payments/cart_detail.html | 3 | ||||
-rw-r--r-- | alphabetlearning/templates/payments/cart_sidepanel.html | 5 | ||||
-rw-r--r-- | alphabetlearning/templates/resources/resource_card_featured.html | 5 | ||||
-rw-r--r-- | alphabetlearning/templates/resources/resource_card_standard.html | 5 |
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> |