Files
SIB/backend/app/api/analytics.py

123 lines
4.3 KiB
Python

from fastapi import APIRouter, Depends
from sqlmodel import Session, select, func
from app.core.database import get_session
from app.models.analytics import AnalyticsEvent
from app.models.user import User
from typing import Optional, Dict
from datetime import datetime, timedelta
from app.api.deps import get_current_user_optional
router = APIRouter()
@router.post("/event")
async def log_event(
event: Dict,
session: Session = Depends(get_session),
current_user: Optional[User] = Depends(get_current_user_optional)
):
user_id = current_user.id if current_user else None
new_event = AnalyticsEvent(
event_name=event.get("event_name"),
user_id=user_id,
screen_name=event.get("screen_name"),
item_id=event.get("item_id"),
properties=event.get("properties", {})
)
session.add(new_event)
session.commit()
return {"status": "ok"}
@router.get("/strategic")
async def get_strategic_analysis(
session: Session = Depends(get_session)
):
"""Deep analysis of how businesses and shuttles are performing."""
# 1. SHUTTLE PERFORMANCE
shuttle_previews = session.exec(
select(AnalyticsEvent.item_id, func.count(AnalyticsEvent.id))
.where(AnalyticsEvent.event_name == "shuttle_view")
.group_by(AnalyticsEvent.item_id)
).all()
shuttle_contacts = session.exec(
select(AnalyticsEvent.item_id, func.count(AnalyticsEvent.id))
.where(AnalyticsEvent.event_name == "shuttle_contact")
.group_by(AnalyticsEvent.item_id)
).all()
shuttle_map = {r[0]: {"views": r[1], "contacts": 0} for r in shuttle_previews if r[0]}
for r in shuttle_contacts:
if r[0] in shuttle_map:
shuttle_map[r[0]]["contacts"] = r[1]
else:
shuttle_map[r[0]] = {"views": 0, "contacts": r[1]}
# 2. BUSINESS PERFORMANCE
biz_views = session.exec(
select(AnalyticsEvent.item_id, func.count(AnalyticsEvent.id))
.where(AnalyticsEvent.event_name == "business_view")
.group_by(AnalyticsEvent.item_id)
).all()
promo_clicks = session.exec(
select(AnalyticsEvent.item_id, func.count(AnalyticsEvent.id))
.where(AnalyticsEvent.event_name == "promo_click")
.group_by(AnalyticsEvent.item_id)
).all()
biz_map = {r[0]: {"views": r[1], "promos": 0} for r in biz_views if r[0]}
for r in promo_clicks:
if r[0] in biz_map:
biz_map[r[0]]["promos"] = r[1]
else:
biz_map[r[0]] = {"views": 0, "promos": r[1]}
# 3. TOP STOPS (CASETAS CON MÁS GENTE)
top_stops = session.exec(
select(AnalyticsEvent.item_id, func.count(AnalyticsEvent.id))
.where(AnalyticsEvent.event_name == "stop_selected")
.group_by(AnalyticsEvent.item_id)
.order_by(func.count(AnalyticsEvent.id).desc())
.limit(10)
).all()
# 4. ACTIVE USERS
total_active_users = session.exec(select(func.count(func.distinct(AnalyticsEvent.user_id))).where(AnalyticsEvent.user_id != None)).one()
# 5. PEAK HOURS BY USER TYPE
hour_expr = func.extract('hour', AnalyticsEvent.timestamp)
reg_usage = session.exec(select(hour_expr, func.count(AnalyticsEvent.id)).where(AnalyticsEvent.user_id != None).group_by(hour_expr)).all()
guest_usage = session.exec(select(hour_expr, func.count(AnalyticsEvent.id)).where(AnalyticsEvent.user_id == None).group_by(hour_expr)).all()
usage_patterns = {
"registered": {int(h): c for h, c in reg_usage},
"guests": {int(h): c for h, c in guest_usage}
}
return {
"shuttles": shuttle_map,
"businesses": biz_map,
"top_stops": [{"id": r[0], "count": r[1]} for r in top_stops],
"users": {
"registered_active": total_active_users,
"patterns": usage_patterns
},
"summary": {
"total_shuttle_contacts": sum(sh[1] for sh in shuttle_contacts),
"total_promo_clicks": sum(p[1] for p in promo_clicks),
"total_biz_views": sum(b[1] for b in biz_views)
}
}
@router.get("/dashboard/stats")
async def get_dashboard_stats(
session: Session = Depends(get_session)
):
# Base dashboard stats for general overview
total_events = session.exec(select(func.count(AnalyticsEvent.id))).one()
return {
"total_events": total_events
}