Add admin stats endpoint for usage tracking

This commit is contained in:
root
2026-03-31 13:49:18 -05:00
parent fcca23e3ca
commit cc8bb0dd09
2 changed files with 102 additions and 1 deletions

View File

@@ -0,0 +1,100 @@
from datetime import datetime, timezone, timedelta
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.database import get_db
from app.core.security import get_current_user
from app.models.user import User
from app.models.playlist import Playlist
from app.models.track import Track
from app.models.recommendation import Recommendation
router = APIRouter(prefix="/admin", tags=["admin"])
ADMIN_EMAILS = ["chris.ryan@deepcutsai.com"]
@router.get("/stats")
async def get_stats(
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
if user.email not in ADMIN_EMAILS:
raise HTTPException(status_code=403, detail="Admin only")
now = datetime.now(timezone.utc)
today = now.replace(hour=0, minute=0, second=0, microsecond=0)
week_ago = now - timedelta(days=7)
month_ago = now - timedelta(days=30)
# User stats
total_users = (await db.execute(select(func.count(User.id)))).scalar() or 0
pro_users = (await db.execute(select(func.count(User.id)).where(User.is_pro == True))).scalar() or 0
# Playlist stats
total_playlists = (await db.execute(select(func.count(Playlist.id)))).scalar() or 0
total_tracks = (await db.execute(select(func.count(Track.id)))).scalar() or 0
# Recommendation stats
total_recs = (await db.execute(select(func.count(Recommendation.id)))).scalar() or 0
recs_today = (await db.execute(
select(func.count(Recommendation.id)).where(Recommendation.created_at >= today)
)).scalar() or 0
recs_this_week = (await db.execute(
select(func.count(Recommendation.id)).where(Recommendation.created_at >= week_ago)
)).scalar() or 0
recs_this_month = (await db.execute(
select(func.count(Recommendation.id)).where(Recommendation.created_at >= month_ago)
)).scalar() or 0
saved_recs = (await db.execute(
select(func.count(Recommendation.id)).where(Recommendation.saved == True)
)).scalar() or 0
disliked_recs = (await db.execute(
select(func.count(Recommendation.id)).where(Recommendation.disliked == True)
)).scalar() or 0
# Per-user breakdown
user_stats_result = await db.execute(
select(
User.id, User.name, User.email, User.is_pro, User.created_at,
func.count(Recommendation.id).label("rec_count"),
)
.outerjoin(Recommendation, Recommendation.user_id == User.id)
.group_by(User.id)
.order_by(User.id)
)
user_breakdown = [
{
"id": row.id,
"name": row.name,
"email": row.email,
"is_pro": row.is_pro,
"created_at": row.created_at.isoformat() if row.created_at else None,
"recommendation_count": row.rec_count,
}
for row in user_stats_result.all()
]
return {
"users": {
"total": total_users,
"pro": pro_users,
"free": total_users - pro_users,
},
"playlists": {
"total": total_playlists,
"total_tracks": total_tracks,
},
"recommendations": {
"total": total_recs,
"today": recs_today,
"this_week": recs_this_week,
"this_month": recs_this_month,
"saved": saved_recs,
"disliked": disliked_recs,
},
"user_breakdown": user_breakdown,
}