wahnsinn vibe
This commit is contained in:
140
backend/apps/cart/__init__.py
Normal file
140
backend/apps/cart/__init__.py
Normal file
@@ -0,0 +1,140 @@
|
||||
import json
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from core.db import get_db
|
||||
from core.redis_client import redis_client
|
||||
from core.security import get_current_user_id
|
||||
|
||||
from .models import Cart, CartItem
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class AddItemIn(BaseModel):
|
||||
product_id: int
|
||||
qty: int = 1
|
||||
|
||||
|
||||
class UpdateItemIn(BaseModel):
|
||||
qty: int
|
||||
|
||||
|
||||
class CartItemOut(BaseModel):
|
||||
product_id: int
|
||||
qty: int
|
||||
name: dict = {}
|
||||
price: float = 0.0
|
||||
image_url: str = ""
|
||||
line_total: float = 0.0
|
||||
|
||||
|
||||
class CartOut(BaseModel):
|
||||
items: list[CartItemOut]
|
||||
subtotal: float
|
||||
|
||||
|
||||
def _get_or_create_cart(db: Session, user_id: int) -> Cart:
|
||||
cart = db.query(Cart).filter_by(user_id=user_id).first()
|
||||
if not cart:
|
||||
cart = Cart(user_id=user_id)
|
||||
db.add(cart)
|
||||
db.commit()
|
||||
db.refresh(cart)
|
||||
return cart
|
||||
|
||||
|
||||
def _cart_to_out(cart: Cart) -> CartOut:
|
||||
items: list[CartItemOut] = []
|
||||
subtotal = 0.0
|
||||
for it in cart.items:
|
||||
raw = redis_client.get(f"product:{it.product_id}")
|
||||
if not raw:
|
||||
continue
|
||||
p = json.loads(raw)
|
||||
line = round(float(p["price"]) * it.qty, 2)
|
||||
subtotal += line
|
||||
items.append(
|
||||
CartItemOut(
|
||||
product_id=it.product_id,
|
||||
qty=it.qty,
|
||||
name=p.get("name", {}),
|
||||
price=float(p["price"]),
|
||||
image_url=p.get("image_url", ""),
|
||||
line_total=line,
|
||||
)
|
||||
)
|
||||
return CartOut(items=items, subtotal=round(subtotal, 2))
|
||||
|
||||
|
||||
@router.get("", response_model=CartOut)
|
||||
def get_cart(user_id: int = Depends(get_current_user_id), db: Session = Depends(get_db)):
|
||||
return _cart_to_out(_get_or_create_cart(db, user_id))
|
||||
|
||||
|
||||
@router.post("/items", response_model=CartOut)
|
||||
def add_item(
|
||||
body: AddItemIn,
|
||||
user_id: int = Depends(get_current_user_id),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
if body.qty < 1:
|
||||
raise HTTPException(400, "qty must be >= 1")
|
||||
if not redis_client.get(f"product:{body.product_id}"):
|
||||
raise HTTPException(404, "Product not found or inactive")
|
||||
cart = _get_or_create_cart(db, user_id)
|
||||
existing = db.query(CartItem).filter_by(cart_id=cart.id, product_id=body.product_id).first()
|
||||
if existing:
|
||||
existing.qty += body.qty
|
||||
else:
|
||||
db.add(CartItem(cart_id=cart.id, product_id=body.product_id, qty=body.qty))
|
||||
db.commit()
|
||||
db.refresh(cart)
|
||||
return _cart_to_out(cart)
|
||||
|
||||
|
||||
@router.put("/items/{product_id}", response_model=CartOut)
|
||||
def update_item(
|
||||
product_id: int,
|
||||
body: UpdateItemIn,
|
||||
user_id: int = Depends(get_current_user_id),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
cart = _get_or_create_cart(db, user_id)
|
||||
item = db.query(CartItem).filter_by(cart_id=cart.id, product_id=product_id).first()
|
||||
if not item:
|
||||
raise HTTPException(404, "Not in cart")
|
||||
if body.qty < 1:
|
||||
db.delete(item)
|
||||
else:
|
||||
item.qty = body.qty
|
||||
db.commit()
|
||||
db.refresh(cart)
|
||||
return _cart_to_out(cart)
|
||||
|
||||
|
||||
@router.delete("/items/{product_id}", response_model=CartOut)
|
||||
def remove_item(
|
||||
product_id: int,
|
||||
user_id: int = Depends(get_current_user_id),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
cart = _get_or_create_cart(db, user_id)
|
||||
item = db.query(CartItem).filter_by(cart_id=cart.id, product_id=product_id).first()
|
||||
if item:
|
||||
db.delete(item)
|
||||
db.commit()
|
||||
db.refresh(cart)
|
||||
return _cart_to_out(cart)
|
||||
|
||||
|
||||
@router.delete("", response_model=CartOut)
|
||||
def clear_cart(user_id: int = Depends(get_current_user_id), db: Session = Depends(get_db)):
|
||||
cart = _get_or_create_cart(db, user_id)
|
||||
for it in list(cart.items):
|
||||
db.delete(it)
|
||||
db.commit()
|
||||
db.refresh(cart)
|
||||
return _cart_to_out(cart)
|
||||
Reference in New Issue
Block a user