flexigo-support-bot / app /analytics.py
victor34593993's picture
wave2: analytics + cross-sell + discounts + stock watches
825b28a verified
Raw
History Blame
1.67 kB
"""Per-tenant analytics event recording + aggregation."""
from __future__ import annotations
from datetime import UTC, datetime, timedelta
from typing import Any
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models import Event
def record(
db: AsyncSession,
tenant_id: int | None,
type_: str,
*,
session_id: str | None = None,
meta: dict[str, Any] | None = None,
) -> None:
"""Queue an analytics event (persisted with the turn's commit)."""
db.add(Event(tenant_id=tenant_id, type=type_, session_id=session_id, meta=meta or {}))
async def summary(db: AsyncSession, tenant_id: int, days: int = 30) -> dict[str, Any]:
since = datetime.now(UTC) - timedelta(days=days)
rows = (
await db.execute(
select(Event.type, func.count())
.where(Event.tenant_id == tenant_id, Event.created_at >= since)
.group_by(Event.type)
)
).all()
counts = {t: int(n) for t, n in rows}
sessions = (
await db.execute(
select(func.count(func.distinct(Event.session_id))).where(
Event.tenant_id == tenant_id, Event.created_at >= since
)
)
).scalar() or 0
return {
"days": days,
"conversations": int(sessions),
"messages": counts.get("turn", 0),
"product_views": counts.get("products_shown", 0),
"cart_links": counts.get("cart_link", 0),
"order_lookups": counts.get("order_lookup", 0),
"escalations": counts.get("escalation", 0),
"stock_watches": counts.get("stock_watch", 0),
"by_type": counts,
}