from typing import Any, Dict, List, Optional, Union from sqlalchemy.orm import Session from app.models.inventory import InventoryItem, InventoryStatus, InventoryTransaction from app.schemas.inventory import ( InventoryItemCreate, InventoryItemUpdate, InventoryTransactionCreate, ) # Inventory Item CRUD operations def get_inventory_item_by_id(db: Session, item_id: str) -> Optional[InventoryItem]: """ Get an inventory item by ID. Args: db: Database session item_id: Inventory item ID Returns: Optional[InventoryItem]: Inventory item if found, None otherwise """ return db.query(InventoryItem).filter(InventoryItem.id == item_id).first() def get_inventory_item_by_product_id(db: Session, product_id: str) -> Optional[InventoryItem]: """ Get an inventory item by product ID. Args: db: Database session product_id: Product ID Returns: Optional[InventoryItem]: Inventory item if found, None otherwise """ return db.query(InventoryItem).filter(InventoryItem.product_id == product_id).first() def get_all_inventory_items( db: Session, skip: int = 0, limit: int = 100, status: Optional[InventoryStatus] = None ) -> List[InventoryItem]: """ Get all inventory items with optional filtering. Args: db: Database session skip: Number of items to skip limit: Maximum number of items to return status: Optional inventory status filter Returns: List[InventoryItem]: List of inventory items """ query = db.query(InventoryItem) if status: query = query.filter(InventoryItem.status == status) return query.offset(skip).limit(limit).all() def create_inventory_item(db: Session, *, obj_in: InventoryItemCreate) -> InventoryItem: """ Create a new inventory item. Args: db: Database session obj_in: Inventory item creation data Returns: InventoryItem: Created inventory item """ db_obj = InventoryItem( product_id=obj_in.product_id, quantity=obj_in.quantity, status=obj_in.status, location=obj_in.location, notes=obj_in.notes, ) db.add(db_obj) db.commit() db.refresh(db_obj) return db_obj def update_inventory_item( db: Session, *, db_obj: InventoryItem, obj_in: Union[InventoryItemUpdate, Dict[str, Any]] ) -> InventoryItem: """ Update an inventory item. Args: db: Database session db_obj: Inventory item to update obj_in: Inventory item update data Returns: InventoryItem: Updated inventory item """ if isinstance(obj_in, dict): update_data = obj_in else: update_data = obj_in.model_dump(exclude_unset=True) for field in update_data: if hasattr(db_obj, field): setattr(db_obj, field, update_data[field]) # Auto-update status based on quantity if "quantity" in update_data: if db_obj.quantity <= 0: db_obj.status = InventoryStatus.OUT_OF_STOCK elif db_obj.quantity < 10: # Arbitrary threshold for low stock db_obj.status = InventoryStatus.LOW_STOCK else: db_obj.status = InventoryStatus.IN_STOCK db.add(db_obj) db.commit() db.refresh(db_obj) return db_obj def delete_inventory_item(db: Session, *, item_id: str) -> InventoryItem: """ Delete an inventory item. Args: db: Database session item_id: Inventory item ID Returns: InventoryItem: Deleted inventory item """ item = db.query(InventoryItem).filter(InventoryItem.id == item_id).first() db.delete(item) db.commit() return item # Inventory Transaction CRUD operations def get_transaction_by_id(db: Session, transaction_id: str) -> Optional[InventoryTransaction]: """ Get an inventory transaction by ID. Args: db: Database session transaction_id: Transaction ID Returns: Optional[InventoryTransaction]: Transaction if found, None otherwise """ return db.query(InventoryTransaction).filter(InventoryTransaction.id == transaction_id).first() def get_transactions_by_product_id( db: Session, product_id: str, skip: int = 0, limit: int = 100 ) -> List[InventoryTransaction]: """ Get inventory transactions by product ID. Args: db: Database session product_id: Product ID skip: Number of transactions to skip limit: Maximum number of transactions to return Returns: List[InventoryTransaction]: List of inventory transactions """ return db.query(InventoryTransaction).filter( InventoryTransaction.product_id == product_id ).order_by(InventoryTransaction.created_at.desc()).offset(skip).limit(limit).all() def create_transaction( db: Session, *, obj_in: InventoryTransactionCreate ) -> InventoryTransaction: """ Create a new inventory transaction. Args: db: Database session obj_in: Transaction creation data Returns: InventoryTransaction: Created transaction """ db_obj = InventoryTransaction( product_id=obj_in.product_id, quantity_change=obj_in.quantity_change, notes=obj_in.notes, transaction_by=obj_in.transaction_by, ) db.add(db_obj) # Update inventory item quantity inventory_item = get_inventory_item_by_product_id(db, product_id=obj_in.product_id) if inventory_item: inventory_item.quantity += obj_in.quantity_change # Update status based on new quantity if inventory_item.quantity <= 0: inventory_item.status = InventoryStatus.OUT_OF_STOCK elif inventory_item.quantity < 10: # Arbitrary threshold for low stock inventory_item.status = InventoryStatus.LOW_STOCK else: inventory_item.status = InventoryStatus.IN_STOCK db.add(inventory_item) db.commit() db.refresh(db_obj) return db_obj