
Features implemented: - Product management with CRUD operations - Category and supplier management - Stock movement tracking with automatic updates - Inventory reports and analytics - SQLite database with Alembic migrations - Health monitoring endpoints - CORS configuration for API access - Comprehensive API documentation - Code quality with Ruff linting and formatting The system provides a complete backend solution for small business inventory management with proper database relationships, stock tracking, and reporting capabilities.
80 lines
2.2 KiB
Python
80 lines
2.2 KiB
Python
from fastapi import APIRouter, Depends
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func
|
|
from app.db.session import get_db
|
|
from app.models.product import Product
|
|
from app.models.stock_movement import StockMovement, MovementType
|
|
|
|
router = APIRouter(prefix="/reports", tags=["reports"])
|
|
|
|
|
|
@router.get("/inventory-summary")
|
|
def get_inventory_summary(db: Session = Depends(get_db)):
|
|
total_products = db.query(Product).count()
|
|
total_stock_value = (
|
|
db.query(func.sum(Product.price * Product.quantity_in_stock)).scalar() or 0
|
|
)
|
|
low_stock_products = (
|
|
db.query(Product)
|
|
.filter(Product.quantity_in_stock <= Product.minimum_stock_level)
|
|
.count()
|
|
)
|
|
|
|
return {
|
|
"total_products": total_products,
|
|
"total_stock_value": round(total_stock_value, 2),
|
|
"low_stock_products": low_stock_products,
|
|
}
|
|
|
|
|
|
@router.get("/low-stock")
|
|
def get_low_stock_products(db: Session = Depends(get_db)):
|
|
products = (
|
|
db.query(Product)
|
|
.filter(Product.quantity_in_stock <= Product.minimum_stock_level)
|
|
.all()
|
|
)
|
|
|
|
return [
|
|
{
|
|
"id": product.id,
|
|
"name": product.name,
|
|
"sku": product.sku,
|
|
"current_stock": product.quantity_in_stock,
|
|
"minimum_stock": product.minimum_stock_level,
|
|
"shortage": product.minimum_stock_level - product.quantity_in_stock,
|
|
}
|
|
for product in products
|
|
]
|
|
|
|
|
|
@router.get("/stock-movements-summary")
|
|
def get_stock_movements_summary(db: Session = Depends(get_db)):
|
|
stock_in = (
|
|
db.query(func.sum(StockMovement.quantity))
|
|
.filter(StockMovement.movement_type == MovementType.IN)
|
|
.scalar()
|
|
or 0
|
|
)
|
|
|
|
stock_out = (
|
|
db.query(func.sum(StockMovement.quantity))
|
|
.filter(StockMovement.movement_type == MovementType.OUT)
|
|
.scalar()
|
|
or 0
|
|
)
|
|
|
|
adjustments = (
|
|
db.query(func.sum(StockMovement.quantity))
|
|
.filter(StockMovement.movement_type == MovementType.ADJUSTMENT)
|
|
.scalar()
|
|
or 0
|
|
)
|
|
|
|
return {
|
|
"total_stock_in": stock_in,
|
|
"total_stock_out": stock_out,
|
|
"total_adjustments": adjustments,
|
|
"net_movement": stock_in - stock_out + adjustments,
|
|
}
|