from datetime import date, datetime from typing import Any, Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.orm import Session from app.api.deps import get_current_user from app.crud import category, item, transaction from app.db.utils import get_db from app.models.user import User from app.schemas.report import ( CategorySummaryItem, CategorySummaryReport, InventoryValueItem, InventoryValueReport, LowStockItem, LowStockReport, TransactionSummaryItem, TransactionSummaryReport, ) router = APIRouter() @router.get("/inventory-value", response_model=InventoryValueReport) def get_inventory_value( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ) -> Any: """ Generate inventory value report. """ items_db = item.get_multi(db) inventory_items = [] total_value = 0.0 for item_db in items_db: item_value = item_db.price * item_db.quantity total_value += item_value inventory_items.append( InventoryValueItem( id=item_db.id, name=item_db.name, sku=item_db.sku, quantity=item_db.quantity, price=item_db.price, total_value=item_value ) ) return InventoryValueReport( total_inventory_value=total_value, items=inventory_items, report_date=datetime.utcnow() ) @router.get("/category-summary", response_model=CategorySummaryReport) def get_category_summary( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ) -> Any: """ Generate category summary report. """ # Get all categories categories_db = category.get_multi(db) summary_items = [] for cat in categories_db: # Get items in this category items_in_category = item.get_by_category_id(db, category_id=cat.id) # Calculate totals item_count = len(items_in_category) total_value = sum(i.price * i.quantity for i in items_in_category) avg_price = sum(i.price for i in items_in_category) / item_count if item_count > 0 else 0 summary_items.append( CategorySummaryItem( category_id=cat.id, category_name=cat.name, item_count=item_count, total_value=total_value, average_price=avg_price ) ) return CategorySummaryReport( categories=summary_items, report_date=datetime.utcnow() ) @router.get("/low-stock", response_model=LowStockReport) def get_low_stock_report( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ) -> Any: """ Generate low stock report. """ # Get items with stock below reorder level low_stock_items_db = item.get_low_stock_items(db) low_stock_items = [] for item_db in low_stock_items_db: low_stock_items.append( LowStockItem( id=item_db.id, name=item_db.name, sku=item_db.sku, quantity=item_db.quantity, reorder_level=item_db.reorder_level, category_name=item_db.category.name if item_db.category else None ) ) return LowStockReport( low_stock_items=low_stock_items, report_date=datetime.utcnow() ) @router.get("/transaction-summary", response_model=TransactionSummaryReport) def get_transaction_summary( start_date: date = Query(..., description="Start date for the report period"), end_date: Optional[date] = Query(None, description="End date for the report period"), db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ) -> Any: """ Generate transaction summary report. """ if end_date is None: end_date = date.today() if start_date > end_date: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Start date must be before end date", ) # Get transaction summary by type summary_data = transaction.get_summary_by_type( db, start_date=start_date, end_date=end_date ) summary_items = [ TransactionSummaryItem( transaction_type=item["transaction_type"], count=item["count"], total_quantity=item["total_quantity"], total_value=item["total_value"] ) for item in summary_data ] return TransactionSummaryReport( start_date=start_date, end_date=end_date, transactions=summary_items, report_date=datetime.utcnow() )