from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app.api.deps import get_db, get_current_active_user, get_current_admin_user from app.crud.crud_inventory import inventory from app.crud.crud_product import product from app.models.user import User as UserModel from app.schemas.inventory import Inventory, InventoryCreate, InventoryUpdate, InventoryAdjustment router = APIRouter() @router.get("/", response_model=List[Inventory]) def read_inventory( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, product_id: Optional[int] = None, location: Optional[str] = None, current_user: UserModel = Depends(get_current_active_user), ) -> Any: """ Retrieve inventory items. Filter by product_id or location if provided. """ items = inventory.get_multi(db, skip=skip, limit=limit) # Apply filters if product_id is not None: items = [item for item in items if item.product_id == product_id] if location is not None: items = [item for item in items if item.location == location] return items @router.post("/", response_model=Inventory) def create_inventory( *, db: Session = Depends(get_db), inventory_in: InventoryCreate, current_user: UserModel = Depends(get_current_admin_user), ) -> Any: """ Create new inventory record. Admin only. """ # Verify product exists prod = product.get(db, id=inventory_in.product_id) if not prod: raise HTTPException(status_code=404, detail="Product not found") # Check if inventory already exists for this product and location existing = inventory.get_by_product_and_location( db, product_id=inventory_in.product_id, location=inventory_in.location ) if existing: raise HTTPException( status_code=400, detail="Inventory record for this product and location already exists. Use adjustment endpoint to modify quantity.", ) new_inventory = inventory.create(db, obj_in=inventory_in) return new_inventory @router.post("/adjust", response_model=Inventory) def adjust_inventory_quantity( *, db: Session = Depends(get_db), adjustment: InventoryAdjustment, current_user: UserModel = Depends(get_current_active_user), ) -> Any: """ Adjust inventory quantity for a product. Use positive quantity to add, negative to remove. """ # Verify product exists prod = product.get(db, id=adjustment.product_id) if not prod: raise HTTPException(status_code=404, detail="Product not found") # Adjust inventory and record transaction result = inventory.adjust_inventory(db, adjustment=adjustment) return result["inventory"] @router.get("/{id}", response_model=Inventory) def read_inventory_item( *, db: Session = Depends(get_db), id: int, current_user: UserModel = Depends(get_current_active_user), ) -> Any: """ Get inventory item by ID. """ item = inventory.get(db, id=id) if not item: raise HTTPException(status_code=404, detail="Inventory item not found") return item @router.put("/{id}", response_model=Inventory) def update_inventory( *, db: Session = Depends(get_db), id: int, inventory_in: InventoryUpdate, current_user: UserModel = Depends(get_current_admin_user), ) -> Any: """ Update an inventory item. Admin only. Note: For regular quantity adjustments, use the /adjust endpoint instead. """ item = inventory.get(db, id=id) if not item: raise HTTPException(status_code=404, detail="Inventory item not found") # If changing product_id, verify product exists if inventory_in.product_id is not None and inventory_in.product_id != item.product_id: prod = product.get(db, id=inventory_in.product_id) if not prod: raise HTTPException(status_code=404, detail="Product not found") # Check if inventory already exists for new product and location existing = inventory.get_by_product_and_location( db, product_id=inventory_in.product_id, location=inventory_in.location or item.location ) if existing and existing.id != id: raise HTTPException( status_code=400, detail="Inventory record for this product and location already exists", ) updated_inventory = inventory.update(db, db_obj=item, obj_in=inventory_in) return updated_inventory @router.delete("/{id}", response_model=Inventory) def delete_inventory( *, db: Session = Depends(get_db), id: int, current_user: UserModel = Depends(get_current_admin_user), ) -> Any: """ Delete an inventory item. Admin only. """ item = inventory.get(db, id=id) if not item: raise HTTPException(status_code=404, detail="Inventory item not found") deleted_inventory = inventory.remove(db, id=id) return deleted_inventory