89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/prabhupadasays/spsays-bff/internal/model"
|
|
)
|
|
|
|
// ListShortURLs returns a page of shortened URLs filtered by an optional query
|
|
// (matched against code or target URL), newest first, with the total count.
|
|
func (r *AdminRepo) ListShortURLs(ctx context.Context, q string, limit, offset int) ([]model.AdminShortURL, int, error) {
|
|
limit = clampLimit(limit)
|
|
rows, err := r.pg.Pool.Query(ctx, `
|
|
SELECT id, code, long_url, content_type, click_count, human_click_count,
|
|
disabled, created_at,
|
|
COUNT(*) OVER() AS total
|
|
FROM shortened_urls
|
|
WHERE ($1 = '' OR code ILIKE '%'||$1||'%' OR long_url ILIKE '%'||$1||'%')
|
|
ORDER BY created_at DESC
|
|
LIMIT $2 OFFSET $3`, q, limit, offset)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("admin list short urls: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
out := []model.AdminShortURL{}
|
|
total := 0
|
|
for rows.Next() {
|
|
var s model.AdminShortURL
|
|
if err := rows.Scan(&s.ID, &s.Code, &s.LongURL, &s.ContentType,
|
|
&s.ClickCount, &s.HumanClickCount, &s.Disabled, &s.CreatedAt, &total); err != nil {
|
|
return nil, 0, fmt.Errorf("scan admin short url: %w", err)
|
|
}
|
|
out = append(out, s)
|
|
}
|
|
return out, total, rows.Err()
|
|
}
|
|
|
|
// ShortURLStats computes created + click counts for the three fixed windows
|
|
// (thresholds passed in), the all-time totals, and — when from/to is given —
|
|
// a custom range (from inclusive, to exclusive). "Created" comes from
|
|
// shortened_urls.created_at; "clicks" from the shortened_url_clicks log.
|
|
func (r *AdminRepo) ShortURLStats(
|
|
ctx context.Context,
|
|
todayStart, weekStart, monthStart time.Time,
|
|
from, to *time.Time,
|
|
) (*model.ShortURLStats, error) {
|
|
var s model.ShortURLStats
|
|
|
|
if err := r.pg.Pool.QueryRow(ctx, `
|
|
SELECT COUNT(*),
|
|
COUNT(*) FILTER (WHERE created_at >= $1),
|
|
COUNT(*) FILTER (WHERE created_at >= $2),
|
|
COUNT(*) FILTER (WHERE created_at >= $3)
|
|
FROM shortened_urls`, todayStart, weekStart, monthStart).
|
|
Scan(&s.TotalURLs, &s.Today.Created, &s.Week.Created, &s.Month.Created); err != nil {
|
|
return nil, fmt.Errorf("short url created stats: %w", err)
|
|
}
|
|
|
|
if err := r.pg.Pool.QueryRow(ctx, `
|
|
SELECT COUNT(*),
|
|
COUNT(*) FILTER (WHERE clicked_at >= $1),
|
|
COUNT(*) FILTER (WHERE clicked_at >= $2),
|
|
COUNT(*) FILTER (WHERE clicked_at >= $3)
|
|
FROM shortened_url_clicks`, todayStart, weekStart, monthStart).
|
|
Scan(&s.TotalClicks, &s.Today.Clicks, &s.Week.Clicks, &s.Month.Clicks); err != nil {
|
|
return nil, fmt.Errorf("short url click stats: %w", err)
|
|
}
|
|
|
|
if from != nil && to != nil {
|
|
var rng model.ShortURLRangeStat
|
|
if err := r.pg.Pool.QueryRow(ctx,
|
|
`SELECT COUNT(*) FROM shortened_urls WHERE created_at >= $1 AND created_at < $2`,
|
|
*from, *to).Scan(&rng.Created); err != nil {
|
|
return nil, fmt.Errorf("short url range created: %w", err)
|
|
}
|
|
if err := r.pg.Pool.QueryRow(ctx,
|
|
`SELECT COUNT(*) FROM shortened_url_clicks WHERE clicked_at >= $1 AND clicked_at < $2`,
|
|
*from, *to).Scan(&rng.Clicks); err != nil {
|
|
return nil, fmt.Errorf("short url range clicks: %w", err)
|
|
}
|
|
s.Range = &rng
|
|
}
|
|
|
|
return &s, nil
|
|
}
|