from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app import crud, models, schemas from app.api import deps from app.models.inventory import InventoryStatus router = APIRouter() # Inventory Item endpoints @router.get("/items/", response_model=List[schemas.InventoryItemWithProduct]) def read_inventory_items( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, status: Optional[InventoryStatus] = None, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve inventory items with optional filtering. """ items = crud.inventory.get_all_inventory_items( db, skip=skip, limit=limit, status=status ) return items @router.post("/items/", response_model=schemas.InventoryItem) def create_inventory_item( *, db: Session = Depends(deps.get_db), item_in: schemas.InventoryItemCreate, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Create new inventory item. Admin only. """ # Check if product exists product = crud.product.get_product_by_id(db, product_id=item_in.product_id) if not product: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Product not found", ) # Check if inventory item for this product already exists existing_item = crud.inventory.get_inventory_item_by_product_id(db, product_id=item_in.product_id) if existing_item: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Inventory item for this product already exists", ) # Create inventory item item = crud.inventory.create_inventory_item(db, obj_in=item_in) # Create initial inventory transaction if item_in.quantity > 0: transaction_in = schemas.InventoryTransactionCreate( product_id=item_in.product_id, quantity_change=item_in.quantity, notes="Initial inventory", transaction_by=current_user.id ) crud.inventory.create_transaction(db, obj_in=transaction_in) return item @router.get("/items/{item_id}", response_model=schemas.InventoryItemWithProduct) def read_inventory_item( *, db: Session = Depends(deps.get_db), item_id: str, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Get inventory item by ID. """ item = crud.inventory.get_inventory_item_by_id(db, item_id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory item not found", ) return item @router.put("/items/{item_id}", response_model=schemas.InventoryItem) def update_inventory_item( *, db: Session = Depends(deps.get_db), item_id: str, item_in: schemas.InventoryItemUpdate, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Update an inventory item. Admin only. """ item = crud.inventory.get_inventory_item_by_id(db, item_id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory item not found", ) # Create transaction if quantity is being updated if item_in.quantity is not None and item_in.quantity != item.quantity: quantity_change = item_in.quantity - item.quantity transaction_in = schemas.InventoryTransactionCreate( product_id=item.product_id, quantity_change=quantity_change, notes=f"Manual inventory adjustment from {item.quantity} to {item_in.quantity}", transaction_by=current_user.id ) crud.inventory.create_transaction(db, obj_in=transaction_in) item = crud.inventory.update_inventory_item(db, db_obj=item, obj_in=item_in) return item @router.delete("/items/{item_id}", response_model=schemas.InventoryItem, status_code=status.HTTP_200_OK) def delete_inventory_item( *, db: Session = Depends(deps.get_db), item_id: str, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Delete an inventory item. Admin only. """ item = crud.inventory.get_inventory_item_by_id(db, item_id=item_id) if not item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Inventory item not found", ) item = crud.inventory.delete_inventory_item(db, item_id=item_id) return item # Inventory Transaction endpoints @router.get("/transactions/", response_model=List[schemas.InventoryTransaction]) def read_transactions( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, product_id: Optional[str] = None, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Retrieve inventory transactions. Admin only. """ if product_id: transactions = crud.inventory.get_transactions_by_product_id( db, product_id=product_id, skip=skip, limit=limit ) else: # Get all transactions - would need to add a method for this # For now, we'll just return an empty list transactions = [] return transactions @router.post("/transactions/", response_model=schemas.InventoryTransaction) def create_transaction( *, db: Session = Depends(deps.get_db), transaction_in: schemas.InventoryTransactionCreate, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Create new inventory transaction. Admin only. """ # Check if product exists product = crud.product.get_product_by_id(db, product_id=transaction_in.product_id) if not product: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Product not found", ) # Check if inventory item exists for this product inventory_item = crud.inventory.get_inventory_item_by_product_id(db, product_id=transaction_in.product_id) if not inventory_item: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="No inventory item found for this product", ) # Set the current user as the transaction creator if not specified if transaction_in.transaction_by is None: transaction_in.transaction_by = current_user.id transaction = crud.inventory.create_transaction(db, obj_in=transaction_in) return transaction @router.get("/transactions/{transaction_id}", response_model=schemas.InventoryTransaction) def read_transaction( *, db: Session = Depends(deps.get_db), transaction_id: str, current_user: models.User = Depends(deps.get_current_admin_user), ) -> Any: """ Get transaction by ID. Admin only. """ transaction = crud.inventory.get_transaction_by_id(db, transaction_id=transaction_id) if not transaction: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Transaction not found", ) return transaction