2026-05-20 10:50:30 +00:00

166 lines
4.9 KiB
Python

from decimal import Decimal
from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from products.models import Product
from .models import Coupon
def get_cart(request):
return request.session.get('cart', {})
def save_cart(request, cart):
request.session['cart'] = cart
request.session.modified = True
def _redirect_after_add(request):
next_url = request.GET.get('next', '').strip()
if next_url.startswith('/'):
return redirect(next_url)
return redirect('cart')
def add_to_cart(request, id):
product = get_object_or_404(Product, id=id)
cart = get_cart(request)
current_qty = cart.get(str(id), 0)
if current_qty + 1 > product.stock:
messages.warning(request, f'Only {product.stock} units of {product.name} are available.')
else:
cart[str(id)] = current_qty + 1
messages.success(request, f'Added {product.name} to your cart.')
save_cart(request, cart)
return _redirect_after_add(request)
def buy_now(request, id):
product = get_object_or_404(Product, id=id)
if product.stock <= 0:
messages.error(request, f'{product.name} is out of stock.')
return redirect('product_detail', product_id=product.id)
request.session['buy_now'] = {str(product.id): 1}
request.session.modified = True
messages.info(request, f'Proceeding to checkout for {product.name}.')
return redirect('checkout')
def update_cart(request, id):
if request.method == 'POST':
qty = int(request.POST.get('quantity', 1))
product = get_object_or_404(Product, id=id)
cart = get_cart(request)
if qty <= 0:
cart.pop(str(id), None)
messages.info(request, f'{product.name} removed from cart.')
elif qty > product.stock:
cart[str(id)] = product.stock
messages.warning(request, f'Quantity adjusted to {product.stock} for {product.name}.')
else:
cart[str(id)] = qty
messages.success(request, f'Cart updated for {product.name}.')
save_cart(request, cart)
return redirect('cart')
def remove_from_cart(request, id):
cart = get_cart(request)
if str(id) in cart:
del cart[str(id)]
messages.info(request, 'Item removed from your cart.')
save_cart(request, cart)
return redirect('cart')
def _get_coupon_for_cart(code, subtotal):
if not code:
return None, Decimal('0')
now = timezone.now()
coupon = Coupon.objects.filter(code=code, active=True).first()
if not coupon:
return None, Decimal('0')
if coupon.valid_from and now < coupon.valid_from:
return None, Decimal('0')
if coupon.valid_to and now > coupon.valid_to:
return None, Decimal('0')
if subtotal < coupon.min_purchase:
return coupon, Decimal('0')
discount = (subtotal * (coupon.discount_percent / Decimal('100'))).quantize(Decimal('0.01'))
return coupon, discount
def apply_coupon(request):
if request.method == 'POST':
code = request.POST.get('coupon_code', '').strip().upper()
request.session['coupon_code'] = code
messages.success(request, f'Coupon {code} applied.')
return redirect('cart')
def remove_coupon(request):
request.session.pop('coupon_code', None)
messages.info(request, 'Coupon removed.')
return redirect('cart')
def cart_view(request):
cart = get_cart(request)
products = []
subtotal = Decimal('0')
item_count = 0
saved_amount = Decimal('0')
for id, qty in cart.items():
product = get_object_or_404(Product, id=int(id))
product.qty = qty
product.subtotal = product.display_price * qty
subtotal += product.subtotal
item_count += qty
saved_amount += Decimal(str(product.savings or 0)) * qty
products.append(product)
shipping = Decimal('60') if products else Decimal('0')
coupon_code = request.session.get('coupon_code', '')
coupon, discount = _get_coupon_for_cart(coupon_code, subtotal)
if coupon_code and not coupon:
request.session.pop('coupon_code', None)
messages.warning(request, 'Coupon is invalid or expired.')
coupon_code = ''
if coupon and subtotal < coupon.min_purchase:
messages.warning(request, f'Coupon requires minimum purchase of Rs. {coupon.min_purchase}.')
discount = Decimal('0')
grand_total = subtotal - discount + shipping
return render(
request,
'cart/cart.html',
{
'products': products,
'subtotal': subtotal,
'total': subtotal,
'shipping': shipping,
'discount': discount,
'grand_total': grand_total,
'coupon_code': coupon_code,
'coupon': coupon,
'item_count': item_count,
'saved_amount': saved_amount,
},
)