from fastapi import APIRouter, Depends, Query import asyncpg from app.core.responses import ok from app.dependencies import get_db, require_admin router = APIRouter(prefix="/stats", tags=["Admin — Dashboard"]) @router.get("/overview") async def overview( db: asyncpg.Connection = Depends(get_db), _: dict = Depends(require_admin), ): # Revenue revenue_today = float(await db.fetchval( "SELECT COALESCE(SUM(total_amount),0) FROM orders WHERE status IN ('paid','processing','shipped','delivered') AND DATE(created_at)=CURRENT_DATE" ) or 0) revenue_week = float(await db.fetchval( "SELECT COALESCE(SUM(total_amount),0) FROM orders WHERE status IN ('paid','processing','shipped','delivered') AND created_at>=date_trunc('week',now())" ) or 0) revenue_month = float(await db.fetchval( "SELECT COALESCE(SUM(total_amount),0) FROM orders WHERE status IN ('paid','processing','shipped','delivered') AND created_at>=date_trunc('month',now())" ) or 0) # Booking counts — what the frontend dashboard shows orders_pending = int(await db.fetchval("SELECT COUNT(*) FROM orders WHERE status='pending'") or 0) bookings_pending = int(await db.fetchval("SELECT COUNT(*) FROM bookings WHERE status='pending'") or 0) bookings_confirmed = int(await db.fetchval( "SELECT COUNT(*) FROM bookings b JOIN time_slots ts ON ts.id=b.slot_id WHERE b.status='confirmed' AND ts.date>=CURRENT_DATE" ) or 0) # Products products_count = int(await db.fetchval("SELECT COUNT(*) FROM products WHERE is_hidden=false") or 0) catalog_value = float(await db.fetchval( "SELECT COALESCE(SUM(price),0) FROM products WHERE is_hidden=false" ) or 0) low_stock_count = int(await db.fetchval( "SELECT COUNT(*) FROM products WHERE stock_quantity<=5 AND is_hidden=false" ) or 0) new_customers_month = int(await db.fetchval( "SELECT COUNT(*) FROM profiles WHERE role='client' AND created_at>=date_trunc('month',now())" ) or 0) return ok({ # Revenue stats "revenue_today": revenue_today, "revenue_week": revenue_week, "revenue_month": revenue_month, # Booking stats (matches frontend dashboard cards) "orders_pending": orders_pending, "bookings_pending": bookings_pending, "bookings_confirmed": bookings_confirmed, "bookings_upcoming": bookings_confirmed, # Product stats (matches frontend dashboard cards) "products_count": products_count, "catalog_value": catalog_value, "low_stock_count": low_stock_count, # Customer stats "new_customers_month": new_customers_month, }) @router.get("/revenue") async def revenue( period: str = Query("month", pattern="^(today|week|month|year)$"), db: asyncpg.Connection = Depends(get_db), _: dict = Depends(require_admin), ): trunc = {"today": "day", "week": "week", "month": "month", "year": "year"}[period] rows = await db.fetch( f""" SELECT date_trunc('{trunc}', created_at) AS period, COALESCE(SUM(total_amount), 0) AS revenue, COUNT(*) AS orders_count FROM orders WHERE status IN ('paid','processing','shipped','delivered') AND created_at >= date_trunc('{trunc}', now()) - interval '12 {trunc}s' GROUP BY 1 ORDER BY 1 DESC """, ) booking_rows = await db.fetch( f""" SELECT date_trunc('{trunc}', b.created_at) AS period, COALESCE(SUM(b.amount_paid), 0) AS revenue, COUNT(*) AS bookings_count FROM bookings b WHERE b.status IN ('confirmed','completed') AND b.created_at >= date_trunc('{trunc}', now()) - interval '12 {trunc}s' GROUP BY 1 ORDER BY 1 DESC """, ) return ok({"orders": [dict(r) for r in rows], "bookings": [dict(r) for r in booking_rows]}) @router.get("/activity", tags=["Admin — Dashboard"]) async def activity( limit: int = Query(20, ge=1, le=100), db: asyncpg.Connection = Depends(get_db), _: dict = Depends(require_admin), ): rows = await db.fetch( """ SELECT al.id, p.full_name AS actor_name, al.action, al.entity_type, al.entity_id, al.metadata, al.created_at FROM activity_log al LEFT JOIN profiles p ON p.id = al.actor_id ORDER BY al.created_at DESC LIMIT $1 """, limit, ) return ok([dict(r) for r in rows])