-- ===================== -- Analytics (date-filtered) -- ===================== -- Shared optional params (nullable = all-time): -- range_start, range_end (exclusive upper bound) -- Required chart params: -- series_start, series_end (inclusive dates) -- Relative window anchor: -- ref_date (inclusive date used for new_today/week/month) -- ===================== -- User Analytics -- ===================== -- name: AnalyticsUsersSummary :one SELECT COUNT(*)::bigint AS total, COUNT(*) FILTER (WHERE u.created_at::date = sqlc.arg('ref_date')::date)::bigint AS new_today, COUNT(*) FILTER ( WHERE u.created_at::date >= sqlc.arg('ref_date')::date - INTERVAL '6 days' AND u.created_at::date <= sqlc.arg('ref_date')::date )::bigint AS new_this_week, COUNT(*) FILTER ( WHERE u.created_at::date >= sqlc.arg('ref_date')::date - INTERVAL '29 days' AND u.created_at::date <= sqlc.arg('ref_date')::date )::bigint AS new_this_month FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsUsersByRole :many SELECT COALESCE(u.role, 'unknown') AS role, COUNT(*)::bigint AS count FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY u.role ORDER BY count DESC; -- name: AnalyticsUsersByStatus :many SELECT COALESCE(u.status, 'unknown') AS status, COUNT(*)::bigint AS count FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY u.status ORDER BY count DESC; -- name: AnalyticsUsersByAgeGroup :many SELECT COALESCE(u.age_group, 'unknown') AS age_group, COUNT(*)::bigint AS count FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY u.age_group ORDER BY count DESC; -- name: AnalyticsUsersByKnowledgeLevel :many SELECT COALESCE(u.knowledge_level, 'unknown') AS knowledge_level, COUNT(*)::bigint AS count FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY u.knowledge_level ORDER BY count DESC; -- name: AnalyticsUsersByRegion :many SELECT COALESCE(u.region, 'unknown') AS region, COUNT(*)::bigint AS count FROM users u WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY u.region ORDER BY count DESC; -- name: AnalyticsUserRegistrationsLast30Days :many SELECT d.date, COUNT(u.id)::bigint AS count FROM generate_series( sqlc.arg('series_start')::date, sqlc.arg('series_end')::date, INTERVAL '1 day' ) AS d(date) LEFT JOIN users u ON u.created_at::date = d.date AND (sqlc.narg('range_start')::timestamptz IS NULL OR u.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR u.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY d.date ORDER BY d.date; -- ===================== -- Subscription Analytics -- ===================== -- name: AnalyticsSubscriptionsSummary :one SELECT COUNT(*)::bigint AS total, COUNT(*) FILTER (WHERE us.status = 'ACTIVE')::bigint AS active, COUNT(*) FILTER (WHERE us.created_at::date = sqlc.arg('ref_date')::date)::bigint AS new_today, COUNT(*) FILTER ( WHERE us.created_at::date >= sqlc.arg('ref_date')::date - INTERVAL '6 days' AND us.created_at::date <= sqlc.arg('ref_date')::date )::bigint AS new_this_week, COUNT(*) FILTER ( WHERE us.created_at::date >= sqlc.arg('ref_date')::date - INTERVAL '29 days' AND us.created_at::date <= sqlc.arg('ref_date')::date )::bigint AS new_this_month FROM user_subscriptions us WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR us.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR us.created_at < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsSubscriptionsByStatus :many SELECT COALESCE(us.status, 'unknown') AS status, COUNT(*)::bigint AS count FROM user_subscriptions us WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR us.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR us.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY us.status ORDER BY count DESC; -- name: AnalyticsRevenueByPlan :many SELECT sp.name AS plan_name, sp.currency, COUNT(p.id)::bigint AS total_payments, COALESCE(SUM(p.amount), 0)::float8 AS total_revenue FROM payments p JOIN subscription_plans sp ON sp.id = p.plan_id WHERE p.status = 'SUCCESS' AND (sqlc.narg('range_start')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) < sqlc.narg('range_end')::timestamptz) GROUP BY sp.name, sp.currency ORDER BY total_revenue DESC; -- name: AnalyticsNewSubscriptionsLast30Days :many SELECT d.date, COUNT(us.id)::bigint AS count FROM generate_series( sqlc.arg('series_start')::date, sqlc.arg('series_end')::date, INTERVAL '1 day' ) AS d(date) LEFT JOIN user_subscriptions us ON us.created_at::date = d.date AND (sqlc.narg('range_start')::timestamptz IS NULL OR us.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR us.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY d.date ORDER BY d.date; -- ===================== -- Payment Analytics -- ===================== -- name: AnalyticsPaymentsSummary :one SELECT COALESCE(SUM(p.amount) FILTER (WHERE p.status = 'SUCCESS'), 0)::float8 AS total_revenue, COALESCE(AVG(p.amount) FILTER (WHERE p.status = 'SUCCESS'), 0)::float8 AS avg_value, COUNT(*)::bigint AS total_payments, COUNT(*) FILTER (WHERE p.status = 'SUCCESS')::bigint AS successful_payments FROM payments p WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsPaymentsByStatus :many SELECT COALESCE(p.status, 'unknown') AS status, COUNT(*)::bigint AS count, COALESCE(SUM(p.amount), 0)::float8 AS total_amount FROM payments p WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) < sqlc.narg('range_end')::timestamptz) GROUP BY p.status ORDER BY count DESC; -- name: AnalyticsPaymentsByMethod :many SELECT COALESCE(p.payment_method, 'unknown') AS payment_method, COUNT(*)::bigint AS count, COALESCE(SUM(p.amount), 0)::float8 AS total_amount FROM payments p WHERE p.status = 'SUCCESS' AND (sqlc.narg('range_start')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) < sqlc.narg('range_end')::timestamptz) GROUP BY p.payment_method ORDER BY count DESC; -- name: AnalyticsRevenueLast30Days :many SELECT d.date, COALESCE(SUM(p.amount), 0)::float8 AS total_revenue FROM generate_series( sqlc.arg('series_start')::date, sqlc.arg('series_end')::date, INTERVAL '1 day' ) AS d(date) LEFT JOIN payments p ON COALESCE(p.paid_at, p.created_at)::date = d.date AND p.status = 'SUCCESS' AND (sqlc.narg('range_start')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR COALESCE(p.paid_at, p.created_at) < sqlc.narg('range_end')::timestamptz) GROUP BY d.date ORDER BY d.date; -- ===================== -- Course Analytics -- ===================== -- name: AnalyticsCourseCounts :one SELECT 0::bigint AS total_categories, 0::bigint AS total_courses, 0::bigint AS total_sub_courses, 0::bigint AS total_videos; -- ===================== -- Content Analytics -- ===================== -- name: AnalyticsQuestionsCounts :one SELECT ( SELECT COUNT(*)::bigint FROM questions q WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR q.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR q.created_at < sqlc.narg('range_end')::timestamptz) ) AS total_questions, ( SELECT COUNT(*)::bigint FROM question_sets qs WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR qs.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR qs.created_at < sqlc.narg('range_end')::timestamptz) ) AS total_question_sets; -- name: AnalyticsQuestionsByType :many SELECT COALESCE(q.question_type, 'unknown') AS question_type, COUNT(*)::bigint AS count FROM questions q WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR q.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR q.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY q.question_type ORDER BY count DESC; -- name: AnalyticsQuestionSetsByType :many SELECT COALESCE(qs.set_type, 'unknown') AS set_type, COUNT(*)::bigint AS count FROM question_sets qs WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR qs.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR qs.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY qs.set_type ORDER BY count DESC; -- ===================== -- Notification Analytics -- ===================== -- name: AnalyticsNotificationsSummary :one SELECT COUNT(*)::bigint AS total, COUNT(*) FILTER (WHERE n.is_read = TRUE)::bigint AS read, COUNT(*) FILTER (WHERE n.is_read = FALSE)::bigint AS unread FROM notifications n WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR n.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR n.created_at < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsNotificationsByChannel :many SELECT COALESCE(n.channel, 'unknown') AS channel, COUNT(*)::bigint AS count FROM notifications n WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR n.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR n.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY n.channel ORDER BY count DESC; -- name: AnalyticsNotificationsByType :many SELECT COALESCE(n.type, 'unknown') AS type, COUNT(*)::bigint AS count FROM notifications n WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR n.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR n.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY n.type ORDER BY count DESC; -- ===================== -- Issue Analytics -- ===================== -- name: AnalyticsIssuesSummary :one SELECT COUNT(*)::bigint AS total, COUNT(*) FILTER (WHERE ri.status = 'resolved')::bigint AS resolved, CASE WHEN COUNT(*) > 0 THEN (COUNT(*) FILTER (WHERE ri.status = 'resolved')::float8 / COUNT(*)::float8) ELSE 0::float8 END AS resolution_rate FROM reported_issues ri WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR ri.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR ri.created_at < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsIssuesByStatus :many SELECT COALESCE(ri.status, 'unknown') AS status, COUNT(*)::bigint AS count FROM reported_issues ri WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR ri.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR ri.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY ri.status ORDER BY count DESC; -- name: AnalyticsIssuesByType :many SELECT COALESCE(ri.issue_type, 'unknown') AS issue_type, COUNT(*)::bigint AS count FROM reported_issues ri WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR ri.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR ri.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY ri.issue_type ORDER BY count DESC; -- ===================== -- Team Analytics -- ===================== -- name: AnalyticsTeamSummary :one SELECT COUNT(*)::bigint AS total_members FROM team_members tm WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR tm.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR tm.created_at < sqlc.narg('range_end')::timestamptz); -- name: AnalyticsTeamByRole :many SELECT COALESCE(tm.team_role, 'unknown') AS team_role, COUNT(*)::bigint AS count FROM team_members tm WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR tm.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR tm.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY tm.team_role ORDER BY count DESC; -- name: AnalyticsTeamByStatus :many SELECT COALESCE(tm.status, 'unknown') AS status, COUNT(*)::bigint AS count FROM team_members tm WHERE (sqlc.narg('range_start')::timestamptz IS NULL OR tm.created_at >= sqlc.narg('range_start')::timestamptz) AND (sqlc.narg('range_end')::timestamptz IS NULL OR tm.created_at < sqlc.narg('range_end')::timestamptz) GROUP BY tm.status ORDER BY count DESC;