Automated Action 1d312e5ff6 Implement Small Business Inventory Management System
- Created FastAPI application with SQLite database
- Implemented models for inventory items, categories, suppliers, and transactions
- Added authentication system with JWT tokens
- Implemented CRUD operations for all models
- Set up Alembic for database migrations
- Added comprehensive API documentation
- Configured Ruff for code linting
2025-06-06 20:27:41 +00:00

212 lines
6.5 KiB
Python

from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from app import crud
from app.api import deps
from app.models.user import User
from app.schemas.item import Item, ItemCreate, ItemUpdate
router = APIRouter()
@router.get("/", response_model=List[Item])
def read_items(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
category_id: Optional[int] = None,
supplier_id: Optional[int] = None,
low_stock: Optional[bool] = False,
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Retrieve inventory items with optional filtering.
"""
if low_stock:
items = crud.item.get_low_stock(db, skip=skip, limit=limit)
elif category_id:
items = crud.item.get_by_category(db, category_id=category_id, skip=skip, limit=limit)
elif supplier_id:
items = crud.item.get_by_supplier(db, supplier_id=supplier_id, skip=skip, limit=limit)
else:
items = crud.item.get_multi(db, skip=skip, limit=limit)
return items
@router.post("/", response_model=Item, status_code=status.HTTP_201_CREATED)
def create_item(
*,
db: Session = Depends(deps.get_db),
item_in: ItemCreate,
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Create new inventory item.
"""
# Check if item with the same SKU or barcode already exists
if item_in.sku:
item = crud.item.get_by_sku(db, sku=item_in.sku)
if item:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Item with this SKU already exists",
)
if item_in.barcode:
item = crud.item.get_by_barcode(db, barcode=item_in.barcode)
if item:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Item with this barcode already exists",
)
# Validate category if provided
if item_in.category_id and not crud.category.get(db, id=item_in.category_id):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="The category doesn't exist",
)
# Validate supplier if provided
if item_in.supplier_id and not crud.supplier.get(db, id=item_in.supplier_id):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="The supplier doesn't exist",
)
item = crud.item.create(db, obj_in=item_in)
return item
@router.get("/{item_id}", response_model=Item)
def read_item(
*,
db: Session = Depends(deps.get_db),
item_id: int,
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Get item by ID.
"""
item = crud.item.get(db, id=item_id)
if not item:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Item not found",
)
return item
@router.put("/{item_id}", response_model=Item)
def update_item(
*,
db: Session = Depends(deps.get_db),
item_id: int,
item_in: ItemUpdate,
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Update an item.
"""
item = crud.item.get(db, id=item_id)
if not item:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Item not found",
)
# Check if SKU is being changed and if it already exists
if item_in.sku and item_in.sku != item.sku:
existing_item = crud.item.get_by_sku(db, sku=item_in.sku)
if existing_item and existing_item.id != item_id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Item with this SKU already exists",
)
# Check if barcode is being changed and if it already exists
if item_in.barcode and item_in.barcode != item.barcode:
existing_item = crud.item.get_by_barcode(db, barcode=item_in.barcode)
if existing_item and existing_item.id != item_id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Item with this barcode already exists",
)
# Validate category if provided
if item_in.category_id and not crud.category.get(db, id=item_in.category_id):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="The category doesn't exist",
)
# Validate supplier if provided
if item_in.supplier_id and not crud.supplier.get(db, id=item_in.supplier_id):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="The supplier doesn't exist",
)
item = crud.item.update(db, db_obj=item, obj_in=item_in)
return item
@router.delete("/{item_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None)
def delete_item(
*,
db: Session = Depends(deps.get_db),
item_id: int,
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Delete an item.
"""
item = crud.item.get(db, id=item_id)
if not item:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Item not found",
)
# Check if the item has any transactions
transactions = crud.transaction.get_by_item(db, item_id=item_id, skip=0, limit=1)
if transactions:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot delete item with transaction history",
)
crud.item.remove(db, id=item_id)
return None
@router.get("/search/", response_model=List[Item])
def search_items(
*,
db: Session = Depends(deps.get_db),
name: Optional[str] = Query(None, min_length=1),
sku: Optional[str] = Query(None, min_length=1),
barcode: Optional[str] = Query(None, min_length=1),
current_user: User = Depends(deps.get_current_user),
) -> Any:
"""
Search for items by name, SKU, or barcode.
"""
if sku:
item = crud.item.get_by_sku(db, sku=sku)
return [item] if item else []
if barcode:
item = crud.item.get_by_barcode(db, barcode=barcode)
return [item] if item else []
if name:
items = db.query(crud.item.model).filter(
crud.item.model.name.ilike(f"%{name}%")
).all()
return items
# If no search parameters are provided, return an empty list
return []