
- Set up project structure and FastAPI application - Create database models for users, products, and inventory - Configure SQLAlchemy and Alembic for database management - Implement JWT authentication - Create API endpoints for user, product, and inventory management - Add admin-only routes and authorization middleware - Add health check endpoint - Update README with documentation - Lint and fix code issues
228 lines
6.1 KiB
Python
228 lines
6.1 KiB
Python
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 |