from typing import Any, List from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.core.deps import get_current_active_superuser, get_current_active_user, get_db from app.models.user import User from app.models.order import OrderStatus from app.schemas.order import Order, OrderCreate, OrderUpdate, OrderList, OrderItemCreate from app.services import order as order_service from app.services import cart as cart_service from app.services import product as product_service router = APIRouter() @router.get("/", response_model=List[OrderList]) def read_orders( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, current_user: User = Depends(get_current_active_user), ) -> Any: """ Get user's orders """ orders = order_service.get_by_user_id( db, user_id=current_user.id, skip=skip, limit=limit ) return orders @router.post("/", response_model=Order) def create_order( *, db: Session = Depends(get_db), order_in: OrderCreate, current_user: User = Depends(get_current_active_user), ) -> Any: """ Create new order from user's cart """ # Ensure cart exists cart = cart_service.get_by_user_id(db, user_id=current_user.id) if not cart: raise HTTPException( status_code=400, detail="Cart is empty", ) # Get cart items cart_items = cart_service.get_cart_items(db, cart_id=cart.id) if not cart_items: raise HTTPException( status_code=400, detail="Cart is empty", ) # Convert cart items to order items order_items = [] for item in cart_items: product = product_service.get_by_id(db, product_id=item.product_id) if not product or not product.is_active: raise HTTPException( status_code=400, detail=f"Product {item.product_id} is unavailable", ) # Check stock if product.stock < item.quantity: raise HTTPException( status_code=400, detail=f"Not enough stock for product {product.name}. Available: {product.stock}", ) order_item = OrderItemCreate( product_id=item.product_id, quantity=item.quantity, price=product.price, ) order_items.append(order_item) # Create order order = order_service.create( db, obj_in=OrderCreate( user_id=current_user.id, shipping_address=order_in.shipping_address, ), items=order_items, ) # Clear cart after order is created cart_service.clear_cart(db, cart_id=cart.id) return order @router.get("/{order_id}", response_model=Order) def read_order( *, db: Session = Depends(get_db), order_id: str, current_user: User = Depends(get_current_active_user), ) -> Any: """ Get order by ID """ order = order_service.get_by_id(db, order_id=order_id) if not order: raise HTTPException( status_code=404, detail="Order not found", ) # Check if user is allowed to access this order if order.user_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=403, detail="Not enough permissions", ) return order @router.put("/{order_id}", response_model=Order) def update_order( *, db: Session = Depends(get_db), order_id: str, order_in: OrderUpdate, current_user: User = Depends(get_current_active_superuser), ) -> Any: """ Update order (admin only) """ order = order_service.get_by_id(db, order_id=order_id) if not order: raise HTTPException( status_code=404, detail="Order not found", ) order = order_service.update(db, db_obj=order, obj_in=order_in) return order @router.post("/{order_id}/cancel", response_model=Order) def cancel_order( *, db: Session = Depends(get_db), order_id: str, current_user: User = Depends(get_current_active_user), ) -> Any: """ Cancel order """ order = order_service.get_by_id(db, order_id=order_id) if not order: raise HTTPException( status_code=404, detail="Order not found", ) # Check if user is allowed to cancel this order if order.user_id != current_user.id and not current_user.is_superuser: raise HTTPException( status_code=403, detail="Not enough permissions", ) # Check if order can be cancelled if order.status != OrderStatus.PENDING: raise HTTPException( status_code=400, detail=f"Order with status {order.status} cannot be cancelled", ) order = order_service.cancel_order(db, order_id=order_id) return order