Skip to content

Commit

Permalink
complete coupon system
Browse files Browse the repository at this point in the history
  • Loading branch information
behshadrhp committed Nov 11, 2023
1 parent fb2025a commit 2cc6a6e
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 47 deletions.
24 changes: 24 additions & 0 deletions cart/cart.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from decimal import Decimal

from django.conf import settings

from coupon.models import Coupon
from shop.models import Product



class Cart:
'''
Shopping Cart.
Expand All @@ -18,6 +22,8 @@ def __init__(self, request):
# save an empty cart in the session
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
# store current applied coupon
self.coupon_id = self.session.get('coupon_id')

def __iter__(self):
"""
Expand Down Expand Up @@ -76,3 +82,21 @@ def clear(self):
def get_total_price(self):
total_price = sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
return round(total_price, 2)

@property
def coupon(self):
if self.coupon_id:
try:
return Coupon.objects.get(id=self.coupon_id)
except Coupon.DoesNotExist:
pass
return None

def get_discount(self):
if self.coupon:
return (self.coupon.discount / Decimal(100)) \
* self.get_total_price()
return Decimal(0)

def get_total_price_after_discount(self):
return self.get_total_price() - self.get_discount()
6 changes: 4 additions & 2 deletions cart/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.views import View

from shop.models import Product
from coupon.forms import CouponApplyForm
from .cart import Cart
from .forms import CartAddProductForm

Expand Down Expand Up @@ -44,6 +45,7 @@ class CartDetailView(View):

def get(self, request):
cart = Cart(request)

context = {'cart': cart}
coupon_apply_form = CouponApplyForm()

context = {'cart': cart, 'coupon_apply_form': coupon_apply_form}
return render(request, 'cart/detail.html', context)
2 changes: 1 addition & 1 deletion core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
path('cart/', include('cart.urls')),
path('order/', include('order.urls')),
path('payment/', include('payment.urls')),
path('coupon/', include('coupon.urls')),
path('coupon/', include('coupon.urls', namespace='coupon')),
]

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Expand Down
9 changes: 9 additions & 0 deletions coupon/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django import forms


class CouponApplyForm(forms.Form):
'''
This class is for Apply Coupon Code in Orders.
'''

code = forms.CharField(max_length=50)
5 changes: 4 additions & 1 deletion coupon/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from django.urls import path
from coupon import views


app_name = 'coupon'

urlpatterns = [

path('apply/', views.CouponApply.as_view(), name='apply'),
]
31 changes: 29 additions & 2 deletions coupon/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.utils import timezone
from django.views import View

# Create your views here.
from .models import Coupon
from .forms import CouponApplyForm



class CouponApply(View):
'''
This class is for apply coupon.
'''

def post(self, request):
now = timezone.now()
form = CouponApplyForm(request.POST)

if form.is_valid():
try:
coupon = Coupon.objects.get(
code__iexact=form['code'],
valid_from__lte=now,
valid_to__gte=now,
active=True
)
request.session['coupon_id'] = coupon.id
except Coupon.DoesNotExist:
request.session['coupon_id'] = None
return redirect('cart:cart_detail')
114 changes: 73 additions & 41 deletions templates/cart/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,69 +7,101 @@

{% block content %}
<div class="container my-5">
<h1 class="mb-4">Your Shopping Cart</h1>

<div class="row">
<div class="col-md-8">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Unit price</th>
<th>Total</th>
<th></th>
</tr>
</thead>
<tbody>
{% for item in cart %}
{% with product=item.product %}
<h1 class="mb-4">Your Shopping Cart</h1>
{% if total_items == 0 %}
<div class="text-center">
<p class="lead">Your cart is empty.</p>
<a href="{% url "shop:product_list" %}" class="btn btn-primary">Start Shopping</a>
</div>
{% else %}
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for item in cart %}
{% with product=item.product %}
<tr>
<td class="d-flex align-items-center">
<div class="mr-3">
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.cover %}{{ product.cover.url }}{% else %}{% static "img/product.jpeg" %}{% endif %}" class="img-fluid" style='width: 100px; border-radius: 10%;'>
</a>
</div>
<div>
{{ product.title }}
</div>
</td>
<td>{{ item.quantity }}</td>
<td>${{ item.price }}</td>
<td>${{ item.total_price }}</td>
<td>
<form action="{% url "cart:cart_remove" product.id %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-sm btn-outline-danger">Remove</button>
</form>
</td>
</tr>
{% endwith %}
{% endfor %}
{% if cart.coupon %}
<tr class="subtotal">
<td>Subtotal</td>
<td colspan="3"></td>
<td class="num">${{ cart.get_total_price|floatformat:2 }}</td>
</tr>
<tr>
<td class="d-flex align-items-center">
<div class="mr-3">
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.cover %}{{ product.cover.url }}{% else %}{% static "img/product.jpeg" %}{% endif %}" style='width: 100px;border-radius: 10%;margin-right: 20px;'>
</a>
</div>
<div>
{{ product.title }}
</div>
</td>
<td>{{ item.quantity }}</td>
<td>${{ item.price }}</td>
<td>${{ item.total_price }}</td>
<td>
<form action="{% url "cart:cart_remove" product.id %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-sm btn-outline-danger">Remove</button>
</form>
"{{ cart.coupon.code }}" coupon
({{ cart.coupon.discount }}% off)
</td>
<td colspan="3"></td>
<td class="num neg">
- ${{ cart.get_discount|floatformat:2 }}
</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</tbody>
</table>
</div>
{% endif %}
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Summary</h5>
<p class="card-text">Total Items: {{ total_items }}</p>
<p class="card-text">Total Price: ${{ cart.get_total_price }}</p>
<a href="{% url 'order:order_create' %}" class="btn btn-primary">Checkout</a>
<a href="{% url "shop:product_list" %}" class="btn btn-light">Continue Shopping</a>
<a href="{% url 'order:order_create' %}" class="btn btn-primary btn-block">Checkout</a>
<a href="{% url "shop:product_list" %}" class="btn btn-light btn-block">Continue Shopping</a>
</div>
</div>
</div>
</div>

{% if total_items == 0 %}
<div class="mt-5 text-center">
<p>Your cart is empty.</p>
<p class="lead">Your cart is empty.</p>
<a href="{% url "shop:product_list" %}" class="btn btn-primary">Start Shopping</a>
</div>
{% endif %}
</div>

<div class="container my-5">
<h3 class="mb-3">Apply a Coupon:</h3>
<form action="{% url "coupon:apply" %}" method="post">
{{ coupon_apply_form }}
<button type="submit" class="btn btn-primary">Apply Coupon</button>
{% csrf_token %}
</form>
</div>
{% endblock %}

0 comments on commit 2cc6a6e

Please sign in to comment.