
- Created FastAPI application with SQLite database - Implemented cart management (create, get, add items, remove items, clear) - Added checkout functionality with payment processing simulation - Set up database models using SQLAlchemy with Cart and CartItem tables - Configured Alembic for database migrations - Added comprehensive API documentation and examples - Included health endpoint and CORS support - Formatted code with ruff linting
204 lines
6.2 KiB
Python
204 lines
6.2 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from typing import List
|
|
import uuid
|
|
|
|
from app.db.session import get_db
|
|
from app.models.cart import Cart, CartItem
|
|
from app.schemas import (
|
|
CartCreate,
|
|
CartResponse,
|
|
CartItemCreate,
|
|
CartItemResponse,
|
|
CheckoutRequest,
|
|
CheckoutResponse,
|
|
)
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/carts/", response_model=CartResponse)
|
|
def create_cart(cart: CartCreate, db: Session = Depends(get_db)):
|
|
db_cart = Cart(user_id=cart.user_id)
|
|
db.add(db_cart)
|
|
db.commit()
|
|
db.refresh(db_cart)
|
|
|
|
# Calculate total
|
|
total = sum(item.price * item.quantity for item in db_cart.items)
|
|
|
|
response = CartResponse.model_validate(db_cart)
|
|
response.total = total
|
|
return response
|
|
|
|
|
|
@router.get("/carts/{cart_id}", response_model=CartResponse)
|
|
def get_cart(cart_id: int, db: Session = Depends(get_db)):
|
|
cart = db.query(Cart).filter(Cart.id == cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
# Calculate total
|
|
total = sum(item.price * item.quantity for item in cart.items)
|
|
|
|
response = CartResponse.model_validate(cart)
|
|
response.total = total
|
|
return response
|
|
|
|
|
|
@router.get("/carts/user/{user_id}", response_model=List[CartResponse])
|
|
def get_user_carts(user_id: str, db: Session = Depends(get_db)):
|
|
carts = db.query(Cart).filter(Cart.user_id == user_id).all()
|
|
|
|
response_carts = []
|
|
for cart in carts:
|
|
total = sum(item.price * item.quantity for item in cart.items)
|
|
cart_response = CartResponse.model_validate(cart)
|
|
cart_response.total = total
|
|
response_carts.append(cart_response)
|
|
|
|
return response_carts
|
|
|
|
|
|
@router.post("/carts/{cart_id}/items/", response_model=CartItemResponse)
|
|
def add_item_to_cart(cart_id: int, item: CartItemCreate, db: Session = Depends(get_db)):
|
|
cart = db.query(Cart).filter(Cart.id == cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
if cart.status != "active":
|
|
raise HTTPException(status_code=400, detail="Cannot add items to inactive cart")
|
|
|
|
# Check if item already exists in cart
|
|
existing_item = (
|
|
db.query(CartItem)
|
|
.filter(CartItem.cart_id == cart_id, CartItem.product_id == item.product_id)
|
|
.first()
|
|
)
|
|
|
|
if existing_item:
|
|
# Update quantity if item exists
|
|
existing_item.quantity += item.quantity
|
|
db.commit()
|
|
db.refresh(existing_item)
|
|
return CartItemResponse.model_validate(existing_item)
|
|
else:
|
|
# Create new item if it doesn't exist
|
|
db_item = CartItem(
|
|
cart_id=cart_id,
|
|
product_id=item.product_id,
|
|
product_name=item.product_name,
|
|
price=item.price,
|
|
quantity=item.quantity,
|
|
)
|
|
db.add(db_item)
|
|
db.commit()
|
|
db.refresh(db_item)
|
|
return CartItemResponse.model_validate(db_item)
|
|
|
|
|
|
@router.put("/carts/{cart_id}/items/{item_id}", response_model=CartItemResponse)
|
|
def update_cart_item(
|
|
cart_id: int, item_id: int, quantity: int, db: Session = Depends(get_db)
|
|
):
|
|
cart = db.query(Cart).filter(Cart.id == cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
if cart.status != "active":
|
|
raise HTTPException(
|
|
status_code=400, detail="Cannot modify items in inactive cart"
|
|
)
|
|
|
|
item = (
|
|
db.query(CartItem)
|
|
.filter(CartItem.id == item_id, CartItem.cart_id == cart_id)
|
|
.first()
|
|
)
|
|
|
|
if item is None:
|
|
raise HTTPException(status_code=404, detail="Cart item not found")
|
|
|
|
if quantity <= 0:
|
|
db.delete(item)
|
|
db.commit()
|
|
return {"message": "Item removed from cart"}
|
|
else:
|
|
item.quantity = quantity
|
|
db.commit()
|
|
db.refresh(item)
|
|
return CartItemResponse.model_validate(item)
|
|
|
|
|
|
@router.delete("/carts/{cart_id}/items/{item_id}")
|
|
def remove_item_from_cart(cart_id: int, item_id: int, db: Session = Depends(get_db)):
|
|
cart = db.query(Cart).filter(Cart.id == cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
if cart.status != "active":
|
|
raise HTTPException(
|
|
status_code=400, detail="Cannot remove items from inactive cart"
|
|
)
|
|
|
|
item = (
|
|
db.query(CartItem)
|
|
.filter(CartItem.id == item_id, CartItem.cart_id == cart_id)
|
|
.first()
|
|
)
|
|
|
|
if item is None:
|
|
raise HTTPException(status_code=404, detail="Cart item not found")
|
|
|
|
db.delete(item)
|
|
db.commit()
|
|
return {"message": "Item removed from cart"}
|
|
|
|
|
|
@router.delete("/carts/{cart_id}")
|
|
def clear_cart(cart_id: int, db: Session = Depends(get_db)):
|
|
cart = db.query(Cart).filter(Cart.id == cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
if cart.status != "active":
|
|
raise HTTPException(status_code=400, detail="Cannot clear inactive cart")
|
|
|
|
# Delete all items in the cart
|
|
db.query(CartItem).filter(CartItem.cart_id == cart_id).delete()
|
|
db.commit()
|
|
return {"message": "Cart cleared successfully"}
|
|
|
|
|
|
@router.post("/checkout/", response_model=CheckoutResponse)
|
|
def checkout(checkout_request: CheckoutRequest, db: Session = Depends(get_db)):
|
|
cart = db.query(Cart).filter(Cart.id == checkout_request.cart_id).first()
|
|
if cart is None:
|
|
raise HTTPException(status_code=404, detail="Cart not found")
|
|
|
|
if cart.status != "active":
|
|
raise HTTPException(status_code=400, detail="Cart is not active")
|
|
|
|
if not cart.items:
|
|
raise HTTPException(status_code=400, detail="Cart is empty")
|
|
|
|
# Calculate total
|
|
total_amount = sum(item.price * item.quantity for item in cart.items)
|
|
|
|
# In a real system, you would process payment here
|
|
# For now, we'll simulate a successful payment
|
|
|
|
# Generate order ID
|
|
order_id = str(uuid.uuid4())
|
|
|
|
# Update cart status to checked_out
|
|
cart.status = "checked_out"
|
|
db.commit()
|
|
|
|
return CheckoutResponse(
|
|
success=True,
|
|
order_id=order_id,
|
|
total_amount=total_amount,
|
|
message="Checkout completed successfully",
|
|
)
|