219 lines
6.2 KiB
Python
219 lines
6.2 KiB
Python
|
|
from flask import Blueprint, render_template, redirect, url_for, flash, request
|
|
from flask_login import login_required, current_user
|
|
from models import db, Cart, CartItem, Product
|
|
|
|
cart_bp = Blueprint('cart', __name__)
|
|
|
|
@cart_bp.route('/cart')
|
|
@login_required
|
|
def view_cart():
|
|
|
|
cart = Cart.query.filter_by(user_id=current_user.id).first()
|
|
if not cart:
|
|
cart = Cart(user_id=current_user.id)
|
|
db.session.add(cart)
|
|
db.session.commit()
|
|
|
|
items = cart.items
|
|
total = 0
|
|
item_details = []
|
|
|
|
for item in items:
|
|
product = Product.query.get(item.product_id)
|
|
if product:
|
|
subtotal = product.price * item.quantity
|
|
total += subtotal
|
|
item_details.append({
|
|
'id': item.id,
|
|
'product': product,
|
|
'quantity': item.quantity,
|
|
'subtotal': subtotal,
|
|
'max_quantity': product.stock
|
|
})
|
|
|
|
return render_template('cart.html', items=item_details, total=total)
|
|
|
|
@cart_bp.route('/add/<int:product_id>')
|
|
@login_required
|
|
def add_to_cart(product_id):
|
|
|
|
cart = Cart.query.filter_by(user_id=current_user.id).first()
|
|
if not cart:
|
|
cart = Cart(user_id=current_user.id)
|
|
db.session.add(cart)
|
|
db.session.commit()
|
|
|
|
product = Product.query.get(product_id)
|
|
if not product:
|
|
flash("Product not found", "danger")
|
|
return redirect(url_for('main.products'))
|
|
|
|
if product.stock <= 0:
|
|
flash(f"Sorry, {product.name} is out of stock", "danger")
|
|
return redirect(url_for('main.products'))
|
|
|
|
cart_item = CartItem.query.filter_by(
|
|
cart_id=cart.id, product_id=product_id).first()
|
|
|
|
if cart_item:
|
|
|
|
if cart_item.quantity + 1 > product.stock:
|
|
flash(f"Only {product.stock} items available in stock", "warning")
|
|
return redirect(url_for('main.products'))
|
|
|
|
cart_item.quantity += 1
|
|
else:
|
|
|
|
cart_item = CartItem(cart_id=cart.id, product_id=product_id, quantity=1)
|
|
db.session.add(cart_item)
|
|
|
|
db.session.commit()
|
|
flash(f"Added {product.name} to cart!", "success")
|
|
|
|
referrer = request.referrer
|
|
if referrer and ('/product/' in referrer or '/products' in referrer):
|
|
return redirect(referrer)
|
|
return redirect(url_for('main.products'))
|
|
|
|
@cart_bp.route('/remove/<int:item_id>', methods=['POST'])
|
|
@login_required
|
|
def remove_from_cart(item_id):
|
|
cart_item = CartItem.query.get_or_404(item_id)
|
|
|
|
if cart_item.cart.user_id != current_user.id:
|
|
flash("You don't have permission to remove this item", "danger")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
product_name = cart_item.product.name
|
|
db.session.delete(cart_item)
|
|
db.session.commit()
|
|
flash(f"{product_name} removed from cart", "info")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
@cart_bp.route('/update/<int:item_id>', methods=['POST'])
|
|
@login_required
|
|
def update_cart(item_id):
|
|
cart_item = CartItem.query.get_or_404(item_id)
|
|
|
|
|
|
if cart_item.cart.user_id != current_user.id:
|
|
flash("You don't have permission to update this item", "danger")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
new_quantity = request.form.get('quantity')
|
|
product = Product.query.get(cart_item.product_id)
|
|
|
|
try:
|
|
new_quantity = int(new_quantity)
|
|
if new_quantity > 0:
|
|
if new_quantity > product.stock:
|
|
flash(
|
|
f"Only {product.stock} items available in stock. Quantity adjusted.", "warning")
|
|
new_quantity = product.stock
|
|
|
|
cart_item.quantity = new_quantity
|
|
db.session.commit()
|
|
flash("Cart updated", "success")
|
|
elif new_quantity == 0:
|
|
db.session.delete(cart_item)
|
|
db.session.commit()
|
|
flash("Item removed from cart", "info")
|
|
else:
|
|
flash("Quantity must be at least 0", "danger")
|
|
|
|
except ValueError:
|
|
flash("Invalid quantity", "danger")
|
|
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
@cart_bp.route('/clear', methods=['POST'])
|
|
@login_required
|
|
def clear_cart():
|
|
cart = Cart.query.filter_by(user_id=current_user.id).first()
|
|
if cart:
|
|
items = cart.items
|
|
if items:
|
|
item_count = len(items)
|
|
|
|
CartItem.query.filter_by(cart_id=cart.id).delete()
|
|
db.session.commit()
|
|
flash(f"Cart cleared ({item_count} items removed)", "info")
|
|
else:
|
|
flash("Your cart is already empty", "info")
|
|
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
@cart_bp.route('/checkout', methods=['GET', 'POST'])
|
|
@login_required
|
|
def checkout():
|
|
cart = Cart.query.filter_by(user_id=current_user.id).first()
|
|
if not cart or not cart.items:
|
|
flash("Your cart is empty", "warning")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
for item in cart.items:
|
|
product = Product.query.get(item.product_id)
|
|
if product.stock < item.quantity:
|
|
flash(
|
|
f"Sorry, {product.name} only has {product.stock} items in stock (you have {item.quantity} in cart)", "danger")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
if request.method == 'POST':
|
|
try:
|
|
total = 0
|
|
order_items = []
|
|
|
|
for item in cart.items:
|
|
product = Product.query.get(item.product_id)
|
|
|
|
product.stock -= item.quantity
|
|
|
|
total += product.price * item.quantity
|
|
|
|
order_items.append({
|
|
'product_id': product.id,
|
|
'quantity': item.quantity,
|
|
'price': product.price
|
|
})
|
|
|
|
from models import Order, OrderItem
|
|
from datetime import datetime
|
|
|
|
order = Order(user_id=current_user.id, created_at=datetime.utcnow())
|
|
db.session.add(order)
|
|
db.session.flush()
|
|
|
|
for item_data in order_items:
|
|
order_item = OrderItem(
|
|
order_id=order.id,
|
|
product_id=item_data['product_id'],
|
|
quantity=item_data['quantity']
|
|
)
|
|
db.session.add(order_item)
|
|
|
|
CartItem.query.filter_by(cart_id=cart.id).delete()
|
|
|
|
db.session.commit()
|
|
|
|
flash(f"Order placed successfully! Total: ${total:.2f}", "success")
|
|
return redirect(url_for('user.profile'))
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
flash(f"Checkout failed: {str(e)}", "danger")
|
|
return redirect(url_for('cart.view_cart'))
|
|
|
|
total = sum(item.product.price * item.quantity for item in cart.items)
|
|
return render_template('checkout.html', cart=cart, total=total)
|
|
|
|
@cart_bp.route('/count')
|
|
@login_required
|
|
def cart_count():
|
|
cart = Cart.query.filter_by(user_id=current_user.id).first()
|
|
if cart:
|
|
count = sum(item.quantity for item in cart.items)
|
|
else:
|
|
count = 0
|
|
return str(count)
|