Initial commit: SIBU 2.0 MISSION
This commit is contained in:
122
backend/app/api/analytics.py
Normal file
122
backend/app/api/analytics.py
Normal file
@ -0,0 +1,122 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user