from fastapi import APIRouter, Depends, HTTPException, status from sqlmodel import Session, select from app.core.db import get_session from app.core.auth import require_any_access, require_write_access, require_admin from app.schemas.models import Inventory, Product from app.schemas.schemas import ( InventoryCreate, InventoryUpdate, InventoryResponse, UserResponse ) from typing import List router = APIRouter(prefix="/inventory", tags=["inventory"]) # Create Inventory @router.post("/", response_model=InventoryResponse, status_code=status.HTTP_201_CREATED) def create_inventory( inventory: InventoryCreate, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_write_access) ): """Create new inventory entry (requires write access).""" # Validate product exists product = session.get(Product, inventory.product_id) if not product: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Product not found" ) # Check if inventory already exists for this product existing_inventory = session.exec( select(Inventory).where(Inventory.product_id == inventory.product_id) ).first() if existing_inventory: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Inventory entry already exists for this product" ) # Create inventory inventory_data = inventory.model_dump() db_inventory = Inventory(**inventory_data) session.add(db_inventory) session.commit() session.refresh(db_inventory) return db_inventory # Read all Inventory @router.get("/", response_model=List[InventoryResponse]) def read_inventory( skip: int = 0, limit: int = 100, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get all inventory entries (requires authentication).""" inventory = session.exec( select(Inventory).offset(skip).limit(limit) ).all() return inventory # Read Inventory by product @router.get("/product/{product_id}", response_model=InventoryResponse) def read_inventory_by_product( product_id: int, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get inventory for a specific product (requires authentication).""" # Validate product exists product = session.get(Product, product_id) if not product: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Product not found" ) inventory = session.exec( select(Inventory).where(Inventory.product_id == product_id) ).first() if not inventory: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory not found for this product" ) return inventory # Read single Inventory by ID @router.get("/{inventory_id}", response_model=InventoryResponse) def read_inventory_by_id( inventory_id: int, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_any_access) ): """Get specific inventory entry by ID (requires authentication).""" inventory = session.get(Inventory, inventory_id) if not inventory: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory entry not found" ) return inventory # Update Inventory @router.put("/{inventory_id}", response_model=InventoryResponse) def update_inventory( inventory_id: int, inventory: InventoryUpdate, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_write_access) ): """Update specific inventory entry (requires write access).""" db_inventory = session.get(Inventory, inventory_id) if not db_inventory: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory entry not found" ) update_data = inventory.model_dump(exclude_unset=True) # Validate product if being updated if "product_id" in update_data: product = session.get(Product, update_data["product_id"]) if not product: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Product not found" ) # Check for duplicate product (excluding current record) existing_inventory = session.exec( select(Inventory).where( Inventory.product_id == update_data["product_id"], Inventory.id != inventory_id ) ).first() if existing_inventory: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Inventory entry already exists for this product" ) # Update inventory for key, value in update_data.items(): setattr(db_inventory, key, value) session.add(db_inventory) session.commit() session.refresh(db_inventory) return db_inventory # Delete Inventory @router.delete("/{inventory_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_inventory( inventory_id: int, session: Session = Depends(get_session), current_user: UserResponse = Depends(require_admin) ): """Delete specific inventory entry (admin only).""" inventory = session.get(Inventory, inventory_id) if not inventory: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory entry not found" ) session.delete(inventory) session.commit() return None