948 lines
24 KiB
Go
948 lines
24 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: analytics.sql
|
|
|
|
package dbgen
|
|
|
|
import (
|
|
"context"
|
|
)
|
|
|
|
const AnalyticsCourseCounts = `-- name: AnalyticsCourseCounts :one
|
|
|
|
SELECT
|
|
(SELECT COUNT(*)::bigint FROM course_categories) AS total_categories,
|
|
(SELECT COUNT(*)::bigint FROM courses) AS total_courses,
|
|
(SELECT COUNT(*)::bigint FROM sub_courses) AS total_sub_courses,
|
|
(SELECT COUNT(*)::bigint FROM sub_course_videos) AS total_videos
|
|
`
|
|
|
|
type AnalyticsCourseCountsRow struct {
|
|
TotalCategories int64 `json:"total_categories"`
|
|
TotalCourses int64 `json:"total_courses"`
|
|
TotalSubCourses int64 `json:"total_sub_courses"`
|
|
TotalVideos int64 `json:"total_videos"`
|
|
}
|
|
|
|
// =====================
|
|
// Course Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsCourseCounts(ctx context.Context) (AnalyticsCourseCountsRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsCourseCounts)
|
|
var i AnalyticsCourseCountsRow
|
|
err := row.Scan(
|
|
&i.TotalCategories,
|
|
&i.TotalCourses,
|
|
&i.TotalSubCourses,
|
|
&i.TotalVideos,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsIssuesByStatus = `-- name: AnalyticsIssuesByStatus :many
|
|
SELECT
|
|
COALESCE(status, 'unknown') AS status,
|
|
COUNT(*)::bigint AS count
|
|
FROM reported_issues
|
|
GROUP BY status
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsIssuesByStatusRow struct {
|
|
Status string `json:"status"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsIssuesByStatus(ctx context.Context) ([]AnalyticsIssuesByStatusRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsIssuesByStatus)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsIssuesByStatusRow
|
|
for rows.Next() {
|
|
var i AnalyticsIssuesByStatusRow
|
|
if err := rows.Scan(&i.Status, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsIssuesByType = `-- name: AnalyticsIssuesByType :many
|
|
SELECT
|
|
COALESCE(issue_type, 'unknown') AS issue_type,
|
|
COUNT(*)::bigint AS count
|
|
FROM reported_issues
|
|
GROUP BY issue_type
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsIssuesByTypeRow struct {
|
|
IssueType string `json:"issue_type"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsIssuesByType(ctx context.Context) ([]AnalyticsIssuesByTypeRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsIssuesByType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsIssuesByTypeRow
|
|
for rows.Next() {
|
|
var i AnalyticsIssuesByTypeRow
|
|
if err := rows.Scan(&i.IssueType, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsIssuesSummary = `-- name: AnalyticsIssuesSummary :one
|
|
|
|
SELECT
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE status = 'resolved')::bigint AS resolved,
|
|
CASE
|
|
WHEN COUNT(*) > 0 THEN (COUNT(*) FILTER (WHERE status = 'resolved')::float8 / COUNT(*)::float8)
|
|
ELSE 0::float8
|
|
END AS resolution_rate
|
|
FROM reported_issues
|
|
`
|
|
|
|
type AnalyticsIssuesSummaryRow struct {
|
|
Total int64 `json:"total"`
|
|
Resolved int64 `json:"resolved"`
|
|
ResolutionRate float64 `json:"resolution_rate"`
|
|
}
|
|
|
|
// =====================
|
|
// Issue Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsIssuesSummary(ctx context.Context) (AnalyticsIssuesSummaryRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsIssuesSummary)
|
|
var i AnalyticsIssuesSummaryRow
|
|
err := row.Scan(&i.Total, &i.Resolved, &i.ResolutionRate)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsNewSubscriptionsLast30Days = `-- name: AnalyticsNewSubscriptionsLast30Days :many
|
|
SELECT
|
|
d.date,
|
|
COUNT(us.id)::bigint AS count
|
|
FROM generate_series(
|
|
CURRENT_DATE - INTERVAL '29 days',
|
|
CURRENT_DATE,
|
|
INTERVAL '1 day'
|
|
) AS d(date)
|
|
LEFT JOIN user_subscriptions us ON us.created_at::date = d.date
|
|
GROUP BY d.date
|
|
ORDER BY d.date
|
|
`
|
|
|
|
type AnalyticsNewSubscriptionsLast30DaysRow struct {
|
|
Date interface{} `json:"date"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsNewSubscriptionsLast30Days(ctx context.Context) ([]AnalyticsNewSubscriptionsLast30DaysRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsNewSubscriptionsLast30Days)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsNewSubscriptionsLast30DaysRow
|
|
for rows.Next() {
|
|
var i AnalyticsNewSubscriptionsLast30DaysRow
|
|
if err := rows.Scan(&i.Date, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsNotificationsByChannel = `-- name: AnalyticsNotificationsByChannel :many
|
|
SELECT
|
|
COALESCE(channel, 'unknown') AS channel,
|
|
COUNT(*)::bigint AS count
|
|
FROM notifications
|
|
GROUP BY channel
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsNotificationsByChannelRow struct {
|
|
Channel string `json:"channel"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsNotificationsByChannel(ctx context.Context) ([]AnalyticsNotificationsByChannelRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsNotificationsByChannel)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsNotificationsByChannelRow
|
|
for rows.Next() {
|
|
var i AnalyticsNotificationsByChannelRow
|
|
if err := rows.Scan(&i.Channel, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsNotificationsByType = `-- name: AnalyticsNotificationsByType :many
|
|
SELECT
|
|
COALESCE(type, 'unknown') AS type,
|
|
COUNT(*)::bigint AS count
|
|
FROM notifications
|
|
GROUP BY type
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsNotificationsByTypeRow struct {
|
|
Type string `json:"type"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsNotificationsByType(ctx context.Context) ([]AnalyticsNotificationsByTypeRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsNotificationsByType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsNotificationsByTypeRow
|
|
for rows.Next() {
|
|
var i AnalyticsNotificationsByTypeRow
|
|
if err := rows.Scan(&i.Type, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsNotificationsSummary = `-- name: AnalyticsNotificationsSummary :one
|
|
|
|
SELECT
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE is_read = TRUE)::bigint AS read,
|
|
COUNT(*) FILTER (WHERE is_read = FALSE)::bigint AS unread
|
|
FROM notifications
|
|
`
|
|
|
|
type AnalyticsNotificationsSummaryRow struct {
|
|
Total int64 `json:"total"`
|
|
Read int64 `json:"read"`
|
|
Unread int64 `json:"unread"`
|
|
}
|
|
|
|
// =====================
|
|
// Notification Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsNotificationsSummary(ctx context.Context) (AnalyticsNotificationsSummaryRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsNotificationsSummary)
|
|
var i AnalyticsNotificationsSummaryRow
|
|
err := row.Scan(&i.Total, &i.Read, &i.Unread)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsPaymentsByMethod = `-- name: AnalyticsPaymentsByMethod :many
|
|
SELECT
|
|
COALESCE(payment_method, 'unknown') AS payment_method,
|
|
COUNT(*)::bigint AS count,
|
|
COALESCE(SUM(amount), 0)::float8 AS total_amount
|
|
FROM payments
|
|
WHERE status = 'SUCCESS'
|
|
GROUP BY payment_method
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsPaymentsByMethodRow struct {
|
|
PaymentMethod string `json:"payment_method"`
|
|
Count int64 `json:"count"`
|
|
TotalAmount float64 `json:"total_amount"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsPaymentsByMethod(ctx context.Context) ([]AnalyticsPaymentsByMethodRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsPaymentsByMethod)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsPaymentsByMethodRow
|
|
for rows.Next() {
|
|
var i AnalyticsPaymentsByMethodRow
|
|
if err := rows.Scan(&i.PaymentMethod, &i.Count, &i.TotalAmount); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsPaymentsByStatus = `-- name: AnalyticsPaymentsByStatus :many
|
|
SELECT
|
|
COALESCE(status, 'unknown') AS status,
|
|
COUNT(*)::bigint AS count,
|
|
COALESCE(SUM(amount), 0)::float8 AS total_amount
|
|
FROM payments
|
|
GROUP BY status
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsPaymentsByStatusRow struct {
|
|
Status string `json:"status"`
|
|
Count int64 `json:"count"`
|
|
TotalAmount float64 `json:"total_amount"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsPaymentsByStatus(ctx context.Context) ([]AnalyticsPaymentsByStatusRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsPaymentsByStatus)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsPaymentsByStatusRow
|
|
for rows.Next() {
|
|
var i AnalyticsPaymentsByStatusRow
|
|
if err := rows.Scan(&i.Status, &i.Count, &i.TotalAmount); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsPaymentsSummary = `-- name: AnalyticsPaymentsSummary :one
|
|
|
|
SELECT
|
|
COALESCE(SUM(amount) FILTER (WHERE status = 'SUCCESS'), 0)::float8 AS total_revenue,
|
|
COALESCE(AVG(amount) FILTER (WHERE status = 'SUCCESS'), 0)::float8 AS avg_value,
|
|
COUNT(*)::bigint AS total_payments,
|
|
COUNT(*) FILTER (WHERE status = 'SUCCESS')::bigint AS successful_payments
|
|
FROM payments
|
|
`
|
|
|
|
type AnalyticsPaymentsSummaryRow struct {
|
|
TotalRevenue float64 `json:"total_revenue"`
|
|
AvgValue float64 `json:"avg_value"`
|
|
TotalPayments int64 `json:"total_payments"`
|
|
SuccessfulPayments int64 `json:"successful_payments"`
|
|
}
|
|
|
|
// =====================
|
|
// Payment Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsPaymentsSummary(ctx context.Context) (AnalyticsPaymentsSummaryRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsPaymentsSummary)
|
|
var i AnalyticsPaymentsSummaryRow
|
|
err := row.Scan(
|
|
&i.TotalRevenue,
|
|
&i.AvgValue,
|
|
&i.TotalPayments,
|
|
&i.SuccessfulPayments,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsQuestionSetsByType = `-- name: AnalyticsQuestionSetsByType :many
|
|
SELECT
|
|
COALESCE(set_type, 'unknown') AS set_type,
|
|
COUNT(*)::bigint AS count
|
|
FROM question_sets
|
|
GROUP BY set_type
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsQuestionSetsByTypeRow struct {
|
|
SetType string `json:"set_type"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsQuestionSetsByType(ctx context.Context) ([]AnalyticsQuestionSetsByTypeRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsQuestionSetsByType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsQuestionSetsByTypeRow
|
|
for rows.Next() {
|
|
var i AnalyticsQuestionSetsByTypeRow
|
|
if err := rows.Scan(&i.SetType, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsQuestionsByType = `-- name: AnalyticsQuestionsByType :many
|
|
SELECT
|
|
COALESCE(question_type, 'unknown') AS question_type,
|
|
COUNT(*)::bigint AS count
|
|
FROM questions
|
|
GROUP BY question_type
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsQuestionsByTypeRow struct {
|
|
QuestionType string `json:"question_type"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsQuestionsByType(ctx context.Context) ([]AnalyticsQuestionsByTypeRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsQuestionsByType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsQuestionsByTypeRow
|
|
for rows.Next() {
|
|
var i AnalyticsQuestionsByTypeRow
|
|
if err := rows.Scan(&i.QuestionType, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsQuestionsCounts = `-- name: AnalyticsQuestionsCounts :one
|
|
|
|
SELECT
|
|
(SELECT COUNT(*)::bigint FROM questions) AS total_questions,
|
|
(SELECT COUNT(*)::bigint FROM question_sets) AS total_question_sets
|
|
`
|
|
|
|
type AnalyticsQuestionsCountsRow struct {
|
|
TotalQuestions int64 `json:"total_questions"`
|
|
TotalQuestionSets int64 `json:"total_question_sets"`
|
|
}
|
|
|
|
// =====================
|
|
// Content Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsQuestionsCounts(ctx context.Context) (AnalyticsQuestionsCountsRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsQuestionsCounts)
|
|
var i AnalyticsQuestionsCountsRow
|
|
err := row.Scan(&i.TotalQuestions, &i.TotalQuestionSets)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsRevenueByPlan = `-- 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'
|
|
GROUP BY sp.name, sp.currency
|
|
ORDER BY total_revenue DESC
|
|
`
|
|
|
|
type AnalyticsRevenueByPlanRow struct {
|
|
PlanName string `json:"plan_name"`
|
|
Currency string `json:"currency"`
|
|
TotalPayments int64 `json:"total_payments"`
|
|
TotalRevenue float64 `json:"total_revenue"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsRevenueByPlan(ctx context.Context) ([]AnalyticsRevenueByPlanRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsRevenueByPlan)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsRevenueByPlanRow
|
|
for rows.Next() {
|
|
var i AnalyticsRevenueByPlanRow
|
|
if err := rows.Scan(
|
|
&i.PlanName,
|
|
&i.Currency,
|
|
&i.TotalPayments,
|
|
&i.TotalRevenue,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsRevenueLast30Days = `-- name: AnalyticsRevenueLast30Days :many
|
|
SELECT
|
|
d.date,
|
|
COALESCE(SUM(p.amount), 0)::float8 AS total_revenue
|
|
FROM generate_series(
|
|
CURRENT_DATE - INTERVAL '29 days',
|
|
CURRENT_DATE,
|
|
INTERVAL '1 day'
|
|
) AS d(date)
|
|
LEFT JOIN payments p ON p.paid_at::date = d.date AND p.status = 'SUCCESS'
|
|
GROUP BY d.date
|
|
ORDER BY d.date
|
|
`
|
|
|
|
type AnalyticsRevenueLast30DaysRow struct {
|
|
Date interface{} `json:"date"`
|
|
TotalRevenue float64 `json:"total_revenue"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsRevenueLast30Days(ctx context.Context) ([]AnalyticsRevenueLast30DaysRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsRevenueLast30Days)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsRevenueLast30DaysRow
|
|
for rows.Next() {
|
|
var i AnalyticsRevenueLast30DaysRow
|
|
if err := rows.Scan(&i.Date, &i.TotalRevenue); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsSubscriptionsByStatus = `-- name: AnalyticsSubscriptionsByStatus :many
|
|
SELECT
|
|
COALESCE(status, 'unknown') AS status,
|
|
COUNT(*)::bigint AS count
|
|
FROM user_subscriptions
|
|
GROUP BY status
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsSubscriptionsByStatusRow struct {
|
|
Status string `json:"status"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsSubscriptionsByStatus(ctx context.Context) ([]AnalyticsSubscriptionsByStatusRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsSubscriptionsByStatus)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsSubscriptionsByStatusRow
|
|
for rows.Next() {
|
|
var i AnalyticsSubscriptionsByStatusRow
|
|
if err := rows.Scan(&i.Status, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsSubscriptionsSummary = `-- name: AnalyticsSubscriptionsSummary :one
|
|
|
|
SELECT
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE status = 'ACTIVE')::bigint AS active,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE)::bigint AS new_today,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE - INTERVAL '7 days')::bigint AS new_this_week,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE - INTERVAL '30 days')::bigint AS new_this_month
|
|
FROM user_subscriptions
|
|
`
|
|
|
|
type AnalyticsSubscriptionsSummaryRow struct {
|
|
Total int64 `json:"total"`
|
|
Active int64 `json:"active"`
|
|
NewToday int64 `json:"new_today"`
|
|
NewThisWeek int64 `json:"new_this_week"`
|
|
NewThisMonth int64 `json:"new_this_month"`
|
|
}
|
|
|
|
// =====================
|
|
// Subscription Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsSubscriptionsSummary(ctx context.Context) (AnalyticsSubscriptionsSummaryRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsSubscriptionsSummary)
|
|
var i AnalyticsSubscriptionsSummaryRow
|
|
err := row.Scan(
|
|
&i.Total,
|
|
&i.Active,
|
|
&i.NewToday,
|
|
&i.NewThisWeek,
|
|
&i.NewThisMonth,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const AnalyticsTeamByRole = `-- name: AnalyticsTeamByRole :many
|
|
SELECT
|
|
COALESCE(team_role, 'unknown') AS team_role,
|
|
COUNT(*)::bigint AS count
|
|
FROM team_members
|
|
GROUP BY team_role
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsTeamByRoleRow struct {
|
|
TeamRole string `json:"team_role"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsTeamByRole(ctx context.Context) ([]AnalyticsTeamByRoleRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsTeamByRole)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsTeamByRoleRow
|
|
for rows.Next() {
|
|
var i AnalyticsTeamByRoleRow
|
|
if err := rows.Scan(&i.TeamRole, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsTeamByStatus = `-- name: AnalyticsTeamByStatus :many
|
|
SELECT
|
|
COALESCE(status, 'unknown') AS status,
|
|
COUNT(*)::bigint AS count
|
|
FROM team_members
|
|
GROUP BY status
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsTeamByStatusRow struct {
|
|
Status string `json:"status"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsTeamByStatus(ctx context.Context) ([]AnalyticsTeamByStatusRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsTeamByStatus)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsTeamByStatusRow
|
|
for rows.Next() {
|
|
var i AnalyticsTeamByStatusRow
|
|
if err := rows.Scan(&i.Status, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsTeamSummary = `-- name: AnalyticsTeamSummary :one
|
|
|
|
SELECT
|
|
COUNT(*)::bigint AS total_members
|
|
FROM team_members
|
|
`
|
|
|
|
// =====================
|
|
// Team Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsTeamSummary(ctx context.Context) (int64, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsTeamSummary)
|
|
var total_members int64
|
|
err := row.Scan(&total_members)
|
|
return total_members, err
|
|
}
|
|
|
|
const AnalyticsUserRegistrationsLast30Days = `-- name: AnalyticsUserRegistrationsLast30Days :many
|
|
SELECT
|
|
d.date,
|
|
COUNT(u.id)::bigint AS count
|
|
FROM generate_series(
|
|
CURRENT_DATE - INTERVAL '29 days',
|
|
CURRENT_DATE,
|
|
INTERVAL '1 day'
|
|
) AS d(date)
|
|
LEFT JOIN users u ON u.created_at::date = d.date
|
|
GROUP BY d.date
|
|
ORDER BY d.date
|
|
`
|
|
|
|
type AnalyticsUserRegistrationsLast30DaysRow struct {
|
|
Date interface{} `json:"date"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUserRegistrationsLast30Days(ctx context.Context) ([]AnalyticsUserRegistrationsLast30DaysRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUserRegistrationsLast30Days)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUserRegistrationsLast30DaysRow
|
|
for rows.Next() {
|
|
var i AnalyticsUserRegistrationsLast30DaysRow
|
|
if err := rows.Scan(&i.Date, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersByAgeGroup = `-- name: AnalyticsUsersByAgeGroup :many
|
|
SELECT
|
|
COALESCE(age_group, 'unknown') AS age_group,
|
|
COUNT(*)::bigint AS count
|
|
FROM users
|
|
GROUP BY age_group
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsUsersByAgeGroupRow struct {
|
|
AgeGroup string `json:"age_group"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUsersByAgeGroup(ctx context.Context) ([]AnalyticsUsersByAgeGroupRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUsersByAgeGroup)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUsersByAgeGroupRow
|
|
for rows.Next() {
|
|
var i AnalyticsUsersByAgeGroupRow
|
|
if err := rows.Scan(&i.AgeGroup, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersByKnowledgeLevel = `-- name: AnalyticsUsersByKnowledgeLevel :many
|
|
SELECT
|
|
COALESCE(knowledge_level, 'unknown') AS knowledge_level,
|
|
COUNT(*)::bigint AS count
|
|
FROM users
|
|
GROUP BY knowledge_level
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsUsersByKnowledgeLevelRow struct {
|
|
KnowledgeLevel string `json:"knowledge_level"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUsersByKnowledgeLevel(ctx context.Context) ([]AnalyticsUsersByKnowledgeLevelRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUsersByKnowledgeLevel)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUsersByKnowledgeLevelRow
|
|
for rows.Next() {
|
|
var i AnalyticsUsersByKnowledgeLevelRow
|
|
if err := rows.Scan(&i.KnowledgeLevel, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersByRegion = `-- name: AnalyticsUsersByRegion :many
|
|
SELECT
|
|
COALESCE(region, 'unknown') AS region,
|
|
COUNT(*)::bigint AS count
|
|
FROM users
|
|
GROUP BY region
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsUsersByRegionRow struct {
|
|
Region string `json:"region"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUsersByRegion(ctx context.Context) ([]AnalyticsUsersByRegionRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUsersByRegion)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUsersByRegionRow
|
|
for rows.Next() {
|
|
var i AnalyticsUsersByRegionRow
|
|
if err := rows.Scan(&i.Region, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersByRole = `-- name: AnalyticsUsersByRole :many
|
|
SELECT
|
|
COALESCE(role, 'unknown') AS role,
|
|
COUNT(*)::bigint AS count
|
|
FROM users
|
|
GROUP BY role
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsUsersByRoleRow struct {
|
|
Role string `json:"role"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUsersByRole(ctx context.Context) ([]AnalyticsUsersByRoleRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUsersByRole)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUsersByRoleRow
|
|
for rows.Next() {
|
|
var i AnalyticsUsersByRoleRow
|
|
if err := rows.Scan(&i.Role, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersByStatus = `-- name: AnalyticsUsersByStatus :many
|
|
SELECT
|
|
COALESCE(status, 'unknown') AS status,
|
|
COUNT(*)::bigint AS count
|
|
FROM users
|
|
GROUP BY status
|
|
ORDER BY count DESC
|
|
`
|
|
|
|
type AnalyticsUsersByStatusRow struct {
|
|
Status string `json:"status"`
|
|
Count int64 `json:"count"`
|
|
}
|
|
|
|
func (q *Queries) AnalyticsUsersByStatus(ctx context.Context) ([]AnalyticsUsersByStatusRow, error) {
|
|
rows, err := q.db.Query(ctx, AnalyticsUsersByStatus)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []AnalyticsUsersByStatusRow
|
|
for rows.Next() {
|
|
var i AnalyticsUsersByStatusRow
|
|
if err := rows.Scan(&i.Status, &i.Count); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const AnalyticsUsersSummary = `-- name: AnalyticsUsersSummary :one
|
|
|
|
|
|
SELECT
|
|
COUNT(*)::bigint AS total,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE)::bigint AS new_today,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE - INTERVAL '7 days')::bigint AS new_this_week,
|
|
COUNT(*) FILTER (WHERE created_at >= CURRENT_DATE - INTERVAL '30 days')::bigint AS new_this_month
|
|
FROM users
|
|
`
|
|
|
|
type AnalyticsUsersSummaryRow struct {
|
|
Total int64 `json:"total"`
|
|
NewToday int64 `json:"new_today"`
|
|
NewThisWeek int64 `json:"new_this_week"`
|
|
NewThisMonth int64 `json:"new_this_month"`
|
|
}
|
|
|
|
// =====================
|
|
// Analytics
|
|
// =====================
|
|
// =====================
|
|
// User Analytics
|
|
// =====================
|
|
func (q *Queries) AnalyticsUsersSummary(ctx context.Context) (AnalyticsUsersSummaryRow, error) {
|
|
row := q.db.QueryRow(ctx, AnalyticsUsersSummary)
|
|
var i AnalyticsUsersSummaryRow
|
|
err := row.Scan(
|
|
&i.Total,
|
|
&i.NewToday,
|
|
&i.NewThisWeek,
|
|
&i.NewThisMonth,
|
|
)
|
|
return i, err
|
|
}
|