40 lines
1.4 KiB
Python
40 lines
1.4 KiB
Python
from datetime import datetime, timedelta, timezone
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy import func
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.auth import get_current_admin
|
|
from app.database import get_db
|
|
from app.models import AdminUser, OutboundClick
|
|
from app.schemas import ClickSummaryItem, OutboundClickPublic
|
|
|
|
router = APIRouter(prefix="/api/admin/analytics", tags=["analytics"])
|
|
|
|
|
|
@router.get("/clicks/summary", response_model=list[ClickSummaryItem])
|
|
def click_summary(
|
|
days: int = 30,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
since = datetime.now(timezone.utc) - timedelta(days=max(1, min(days, 365)))
|
|
rows = (
|
|
db.query(OutboundClick.link_kind, func.count(OutboundClick.id))
|
|
.filter(OutboundClick.created_at >= since)
|
|
.group_by(OutboundClick.link_kind)
|
|
.order_by(func.count(OutboundClick.id).desc())
|
|
.all()
|
|
)
|
|
return [ClickSummaryItem(link_kind=kind, count=count) for kind, count in rows]
|
|
|
|
|
|
@router.get("/clicks/recent", response_model=list[OutboundClickPublic])
|
|
def recent_clicks(
|
|
limit: int = 50,
|
|
db: Session = Depends(get_db),
|
|
_: AdminUser = Depends(get_current_admin),
|
|
):
|
|
limit = max(1, min(limit, 200))
|
|
rows = db.query(OutboundClick).order_by(OutboundClick.id.desc()).limit(limit).all()
|
|
return [OutboundClickPublic.model_validate(r) for r in rows]
|