from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.orm import Session from app import crud, schemas from app.database.session import get_db router = APIRouter() @router.get( "/", response_model=List[schemas.Item], status_code=status.HTTP_200_OK, summary="Get all items", description="Retrieve all items with pagination, filtering, and search options", ) def read_items( db: Session = Depends(get_db), query: Optional[str] = Query(None, description="Search text in name and description"), active: Optional[bool] = Query(None, description="Filter by active status"), price_min: Optional[int] = Query(None, description="Minimum price in cents"), price_max: Optional[int] = Query(None, description="Maximum price in cents"), skip: int = Query(0, description="Number of records to skip"), limit: int = Query(100, description="Maximum number of records to return"), ) -> Any: """ Retrieve items with support for: - Text search in name and description - Filtering by active status - Price range filtering - Pagination with skip and limit parameters """ # If search query or price filters are provided, use search method if query is not None or price_min is not None or price_max is not None: items = crud.item.search( db, query=query or "", skip=skip, limit=limit, active=active, price_min=price_min, price_max=price_max ) # Otherwise use existing methods elif active is not None: items = crud.item.get_multi_by_active(db, active=active, skip=skip, limit=limit) else: items = crud.item.get_multi(db, skip=skip, limit=limit) return items @router.get( "/search", response_model=List[schemas.Item], status_code=status.HTTP_200_OK, summary="Search items", description="Search for items by query text in name and description with additional filters", ) def search_items( query: str = Query(..., description="Search text in name and description"), db: Session = Depends(get_db), active: Optional[bool] = Query(None, description="Filter by active status"), price_min: Optional[int] = Query(None, description="Minimum price in cents"), price_max: Optional[int] = Query(None, description="Maximum price in cents"), skip: int = Query(0, description="Number of records to skip"), limit: int = Query(100, description="Maximum number of records to return"), ) -> Any: """ Search for items with support for: - Text search in name and description (required) - Filtering by active status - Price range filtering - Pagination with skip and limit parameters """ items = crud.item.search( db, query=query, skip=skip, limit=limit, active=active, price_min=price_min, price_max=price_max ) return items @router.get( "/{item_id}", response_model=schemas.Item, status_code=status.HTTP_200_OK, summary="Get an item by ID", description="Get a specific item by its ID", ) def read_item( *, db: Session = Depends(get_db), item_id: int, ) -> Any: """ Get an item by ID. """ item = crud.item.get(db=db, id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Item not found", ) return item @router.post( "/", response_model=schemas.Item, status_code=status.HTTP_201_CREATED, summary="Create a new item", description="Create a new item with the provided data", ) def create_item( *, db: Session = Depends(get_db), item_in: schemas.ItemCreate, ) -> Any: """ Create a new item. """ item = crud.item.get_by_name(db=db, name=item_in.name) if item: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"An item with the name '{item_in.name}' already exists", ) item = crud.item.create(db=db, obj_in=item_in) return item @router.put( "/{item_id}", response_model=schemas.Item, status_code=status.HTTP_200_OK, summary="Update an item", description="Update an item with the provided data", ) def update_item( *, db: Session = Depends(get_db), item_id: int, item_in: schemas.ItemUpdate, ) -> Any: """ Update an item. """ item = crud.item.get(db=db, id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Item not found", ) item = crud.item.update(db=db, db_obj=item, obj_in=item_in) return item @router.delete( "/{item_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None, summary="Delete an item", description="Delete an item by its ID", ) def delete_item( *, db: Session = Depends(get_db), item_id: int, ) -> None: """ Delete an item. """ item = crud.item.get(db=db, id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Item not found", ) crud.item.remove(db=db, id=item_id) return None