# /opt/docker/dev/service_finder/backend/app/api/v1/endpoints/reports.py """ Reports endpoints — Zombie API Cleanup. Replaced raw SQL (FROM vehicle.vehicle_expenses) with SQLAlchemy ORM queries using fleet_finance.asset_costs (AssetCost) + CostCategory. """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func, desc from sqlalchemy.orm import selectinload from app.api.deps import get_db, get_current_user from app.models.fleet_finance import AssetCost, CostCategory from app.models.identity import User router = APIRouter() @router.get("/summary/{vehicle_id}") async def get_vehicle_summary( vehicle_id: str, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user) ): """ Összesített jelentés egy járműhöz: kategóriánkénti költségek. Uses fleet_finance.asset_costs (AssetCost) joined with CostCategory. """ # Aggregate costs by category using ORM stmt = ( select( CostCategory.name.label("category"), func.sum(AssetCost.amount_gross).label("total_amount"), func.count(AssetCost.id).label("transaction_count"), ) .join(CostCategory, AssetCost.category_id == CostCategory.id) .where(AssetCost.asset_id == vehicle_id) .group_by(CostCategory.name) ) result = await db.execute(stmt) rows = result.all() total_cost = sum(float(row.total_amount) for row in rows) if rows else 0.0 return { "vehicle_id": vehicle_id, "total_cost": total_cost, "breakdown": [ { "category": row.category, "total_amount": float(row.total_amount), "transaction_count": row.transaction_count, } for row in rows ], } @router.get("/trends/{vehicle_id}") async def get_monthly_trends( vehicle_id: str, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user) ): """ Visszaadja az utolsó 6 hónap költéseit havi bontásban. Uses fleet_finance.asset_costs (AssetCost) with date truncation. """ # Monthly aggregation using ORM-compatible date truncation from sqlalchemy import text as sql_text stmt = ( select( func.to_char(AssetCost.date, "YYYY-MM").label("month"), func.sum(AssetCost.amount_gross).label("monthly_total"), ) .where(AssetCost.asset_id == vehicle_id) .group_by(sql_text("month")) .order_by(desc(sql_text("month"))) .limit(6) ) result = await db.execute(stmt) rows = result.all() return [ {"month": row.month, "monthly_total": float(row.monthly_total)} for row in rows ] @router.get("/summary/latest") async def get_latest_summary( db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user) ): """ Returns a simple summary for the dashboard (mock data for now). This endpoint is called by the frontend dashboard. """ # For now, return mock data to satisfy the frontend return { "total_vehicles": 4, "total_cost_this_month": 1250.50, "most_expensive_category": "Fuel", "trend": "down", "trend_percentage": -5.2, }