Automated Action 0474b30c3f Implement complete bookstore management API with FastAPI
- Added comprehensive book management with CRUD operations
- Implemented inventory tracking with stock management and reservations
- Created order management system with status tracking
- Integrated Stripe payment processing with payment intents
- Added SQLite database with SQLAlchemy ORM and Alembic migrations
- Implemented health check and API documentation endpoints
- Added comprehensive error handling and validation
- Configured CORS middleware for frontend integration
2025-06-25 10:34:27 +00:00

119 lines
5.0 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List
from app.db.session import get_db
from app.models import Inventory, Book
from app.schemas import InventoryCreate, InventoryUpdate, InventoryResponse
router = APIRouter(prefix="/inventory", tags=["inventory"])
@router.post("/", response_model=InventoryResponse)
def create_inventory(inventory: InventoryCreate, db: Session = Depends(get_db)):
book = db.query(Book).filter(Book.id == inventory.book_id).first()
if not book:
raise HTTPException(status_code=404, detail="Book not found")
existing_inventory = db.query(Inventory).filter(Inventory.book_id == inventory.book_id).first()
if existing_inventory:
raise HTTPException(status_code=400, detail="Inventory for this book already exists")
db_inventory = Inventory(**inventory.model_dump())
db.add(db_inventory)
db.commit()
db.refresh(db_inventory)
setattr(db_inventory, 'available_quantity', db_inventory.quantity - db_inventory.reserved_quantity)
return db_inventory
@router.get("/", response_model=List[InventoryResponse])
def get_inventory(
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=1000),
low_stock: bool = Query(False, description="Filter items with low stock"),
db: Session = Depends(get_db)
):
query = db.query(Inventory)
if low_stock:
query = query.filter(Inventory.quantity <= Inventory.reorder_level)
inventories = query.offset(skip).limit(limit).all()
for inventory in inventories:
setattr(inventory, 'available_quantity', inventory.quantity - inventory.reserved_quantity)
return inventories
@router.get("/{inventory_id}", response_model=InventoryResponse)
def get_inventory_item(inventory_id: int, db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory item not found")
setattr(inventory, 'available_quantity', inventory.quantity - inventory.reserved_quantity)
return inventory
@router.get("/book/{book_id}", response_model=InventoryResponse)
def get_inventory_by_book(book_id: int, db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.book_id == book_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory for this book not found")
setattr(inventory, 'available_quantity', inventory.quantity - inventory.reserved_quantity)
return inventory
@router.put("/{inventory_id}", response_model=InventoryResponse)
def update_inventory(inventory_id: int, inventory_update: InventoryUpdate, db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory item not found")
update_data = inventory_update.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(inventory, field, value)
db.commit()
db.refresh(inventory)
setattr(inventory, 'available_quantity', inventory.quantity - inventory.reserved_quantity)
return inventory
@router.post("/{inventory_id}/restock")
def restock_inventory(inventory_id: int, quantity: int = Query(..., gt=0), db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory item not found")
inventory.quantity += quantity
db.commit()
return {"message": f"Restocked {quantity} units. New quantity: {inventory.quantity}"}
@router.post("/{inventory_id}/reserve")
def reserve_inventory(inventory_id: int, quantity: int = Query(..., gt=0), db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory item not found")
available = inventory.quantity - inventory.reserved_quantity
if quantity > available:
raise HTTPException(status_code=400, detail=f"Not enough stock available. Available: {available}")
inventory.reserved_quantity += quantity
db.commit()
return {"message": f"Reserved {quantity} units"}
@router.post("/{inventory_id}/release")
def release_inventory(inventory_id: int, quantity: int = Query(..., gt=0), db: Session = Depends(get_db)):
inventory = db.query(Inventory).filter(Inventory.id == inventory_id).first()
if not inventory:
raise HTTPException(status_code=404, detail="Inventory item not found")
if quantity > inventory.reserved_quantity:
raise HTTPException(status_code=400, detail="Cannot release more than reserved quantity")
inventory.reserved_quantity -= quantity
db.commit()
return {"message": f"Released {quantity} units from reservation"}