Files
CosScene/server/app/api/v1/endpoints/stats.py
T
2026-05-09 16:40:29 +08:00

64 lines
2.5 KiB
Python

from fastapi import APIRouter, Depends
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.deps import get_current_active_user, get_db
from app.models.comment import Comment
from app.models.event import Event, EventRegistration
from app.models.favorite import Favorite
from app.models.promotion import Promotion
from app.models.rating import Rating
from app.models.shooting import ShootingRequest, ShootingApplication
from app.models.spot import Spot
from app.models.user import User
router = APIRouter()
@router.get("/overview")
async def get_stats_overview(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db),
):
if current_user.role not in ("admin", "moderator"):
return {"detail": "Not allowed"}
user_count = (await db.execute(select(func.count(User.id)))).scalar() or 0
spot_count = (await db.execute(select(func.count(Spot.id)))).scalar() or 0
approved_spot_count = (await db.execute(
select(func.count(Spot.id)).where(Spot.audit_status == "approved")
)).scalar() or 0
pending_spot_count = (await db.execute(
select(func.count(Spot.id)).where(Spot.audit_status == "pending")
)).scalar() or 0
comment_count = (await db.execute(select(func.count(Comment.id)))).scalar() or 0
rating_count = (await db.execute(select(func.count(Rating.id)))).scalar() or 0
favorite_count = (await db.execute(select(func.count(Favorite.id)))).scalar() or 0
shooting_count = (await db.execute(select(func.count(ShootingRequest.id)))).scalar() or 0
event_count = (await db.execute(select(func.count(Event.id)))).scalar() or 0
promo_result = await db.execute(
select(
func.coalesce(func.sum(Promotion.impressions), 0),
func.coalesce(func.sum(Promotion.clicks), 0),
)
)
promo_row = promo_result.one()
total_impressions = int(promo_row[0])
total_clicks = int(promo_row[1])
return {
"user_count": user_count,
"spot_count": spot_count,
"approved_spot_count": approved_spot_count,
"pending_spot_count": pending_spot_count,
"comment_count": comment_count,
"rating_count": rating_count,
"favorite_count": favorite_count,
"shooting_count": shooting_count,
"event_count": event_count,
"promo_impressions": total_impressions,
"promo_clicks": total_clicks,
"promo_ctr": round(total_clicks / total_impressions * 100, 2) if total_impressions > 0 else 0,
}