2026-04-17 08:10:45 +08:00
|
|
|
-- name: CreateKolUsageLog :one
|
|
|
|
|
INSERT INTO kol_usage_logs (tenant_id, subscription_id, subscription_prompt_id,
|
|
|
|
|
package_id, prompt_id, prompt_revision_no,
|
|
|
|
|
generation_task_id, status, variables_snapshot,
|
|
|
|
|
schema_snapshot, rendered_prompt_hash)
|
|
|
|
|
VALUES (sqlc.arg(tenant_id)::bigint, sqlc.arg(subscription_id),
|
|
|
|
|
sqlc.arg(subscription_prompt_id), sqlc.arg(package_id),
|
|
|
|
|
sqlc.arg(prompt_id), sqlc.arg(prompt_revision_no),
|
|
|
|
|
sqlc.arg(generation_task_id), 'pending',
|
|
|
|
|
sqlc.arg(variables_snapshot)::jsonb, sqlc.arg(schema_snapshot)::jsonb,
|
|
|
|
|
sqlc.arg(rendered_prompt_hash))
|
|
|
|
|
RETURNING id, tenant_id, generation_task_id, status, created_at;
|
|
|
|
|
|
|
|
|
|
-- name: MarkKolUsageCompleted :exec
|
|
|
|
|
UPDATE kol_usage_logs
|
|
|
|
|
SET status = 'completed', article_id = sqlc.arg(article_id),
|
|
|
|
|
finished_at = NOW()
|
|
|
|
|
WHERE id = sqlc.arg(id)
|
|
|
|
|
AND tenant_id = sqlc.arg(tenant_id)::bigint;
|
|
|
|
|
|
|
|
|
|
-- name: MarkKolUsageFailed :exec
|
|
|
|
|
UPDATE kol_usage_logs
|
|
|
|
|
SET status = 'failed', error_message = sqlc.arg(error_message),
|
|
|
|
|
finished_at = NOW()
|
|
|
|
|
WHERE id = sqlc.arg(id)
|
|
|
|
|
AND tenant_id = sqlc.arg(tenant_id)::bigint;
|
|
|
|
|
|
|
|
|
|
-- name: MarkKolUsageCompletedByTask :exec
|
|
|
|
|
UPDATE kol_usage_logs
|
|
|
|
|
SET status = 'completed', article_id = sqlc.arg(article_id), finished_at = NOW()
|
|
|
|
|
WHERE generation_task_id = sqlc.arg(generation_task_id)
|
|
|
|
|
AND tenant_id = sqlc.arg(tenant_id)::bigint;
|
|
|
|
|
|
|
|
|
|
-- name: MarkKolUsageFailedByTask :exec
|
|
|
|
|
UPDATE kol_usage_logs
|
|
|
|
|
SET status = 'failed', error_message = sqlc.arg(error_message), finished_at = NOW()
|
|
|
|
|
WHERE generation_task_id = sqlc.arg(generation_task_id)
|
|
|
|
|
AND tenant_id = sqlc.arg(tenant_id)::bigint;
|
|
|
|
|
|
|
|
|
|
-- name: GetKolUsageByGenerationTask :one
|
|
|
|
|
SELECT id, tenant_id, package_id, prompt_id, status, created_at
|
|
|
|
|
FROM kol_usage_logs
|
|
|
|
|
WHERE generation_task_id = sqlc.arg(generation_task_id)
|
|
|
|
|
AND tenant_id = sqlc.arg(tenant_id)::bigint;
|
|
|
|
|
|
|
|
|
|
-- name: KolDashboardOverview :one
|
2026-04-17 08:34:12 +08:00
|
|
|
-- Cross-tenant aggregation: KOL owns packages across subscriber tenants.
|
2026-04-17 08:10:45 +08:00
|
|
|
SELECT
|
|
|
|
|
(SELECT COUNT(DISTINCT s.tenant_id) FROM kol_subscriptions s
|
|
|
|
|
WHERE s.package_id = ANY(sqlc.arg(package_ids)::bigint[]) AND s.status='active'
|
|
|
|
|
AND (s.end_at IS NULL OR s.end_at > NOW())) AS total_subs,
|
|
|
|
|
(SELECT COUNT(*) FROM kol_subscriptions s
|
|
|
|
|
WHERE s.package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
AND s.status='active'
|
|
|
|
|
AND s.created_at >= date_trunc('month', NOW())) AS month_subs,
|
|
|
|
|
(SELECT COUNT(*) FROM kol_usage_logs u
|
2026-04-17 08:34:12 +08:00
|
|
|
WHERE u.package_id = ANY(sqlc.arg(package_ids)::bigint[])) AS total_usage,
|
2026-04-17 08:10:45 +08:00
|
|
|
(SELECT COUNT(*) FROM kol_usage_logs u
|
|
|
|
|
WHERE u.package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
AND u.created_at >= date_trunc('month', NOW())) AS month_usage,
|
|
|
|
|
(SELECT COUNT(*) FROM kol_usage_logs u
|
|
|
|
|
WHERE u.package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
AND u.status='failed') AS failure_count;
|
|
|
|
|
|
|
|
|
|
-- name: KolDashboardTrend :many
|
2026-04-17 08:34:12 +08:00
|
|
|
-- Returns a per-day series combining usage count and new subscription count for KOL dashboard.
|
|
|
|
|
WITH days AS (
|
|
|
|
|
SELECT generate_series(
|
|
|
|
|
date_trunc('day', NOW()) - (sqlc.arg(period_days)::int - 1) * INTERVAL '1 day',
|
|
|
|
|
date_trunc('day', NOW()),
|
|
|
|
|
INTERVAL '1 day'
|
|
|
|
|
)::date AS d
|
|
|
|
|
),
|
|
|
|
|
u AS (
|
|
|
|
|
SELECT date_trunc('day', created_at)::date AS d,
|
|
|
|
|
COUNT(*) FILTER (WHERE status = 'completed') AS usages
|
|
|
|
|
FROM kol_usage_logs
|
|
|
|
|
WHERE package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
AND created_at >= NOW() - sqlc.arg(period_days)::int * INTERVAL '1 day'
|
|
|
|
|
GROUP BY 1
|
|
|
|
|
),
|
|
|
|
|
s AS (
|
|
|
|
|
SELECT date_trunc('day', created_at)::date AS d,
|
|
|
|
|
COUNT(*) AS subscriptions
|
|
|
|
|
FROM kol_subscriptions
|
|
|
|
|
WHERE package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
AND status IN ('active', 'expired', 'revoked')
|
|
|
|
|
AND created_at >= NOW() - sqlc.arg(period_days)::int * INTERVAL '1 day'
|
|
|
|
|
GROUP BY 1
|
|
|
|
|
)
|
|
|
|
|
SELECT days.d,
|
|
|
|
|
COALESCE(u.usages, 0)::bigint AS usages,
|
|
|
|
|
COALESCE(s.subscriptions, 0)::bigint AS subscriptions
|
|
|
|
|
FROM days
|
|
|
|
|
LEFT JOIN u ON u.d = days.d
|
|
|
|
|
LEFT JOIN s ON s.d = days.d
|
|
|
|
|
ORDER BY days.d ASC;
|
2026-04-17 08:10:45 +08:00
|
|
|
|
|
|
|
|
-- name: KolUsageCountByPackage :many
|
2026-04-17 08:34:12 +08:00
|
|
|
-- Cross-tenant aggregation for KOL dashboard.
|
2026-04-17 08:10:45 +08:00
|
|
|
SELECT package_id, COUNT(*) AS total,
|
|
|
|
|
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed,
|
|
|
|
|
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed
|
|
|
|
|
FROM kol_usage_logs
|
|
|
|
|
WHERE package_id = ANY(sqlc.arg(package_ids)::bigint[])
|
|
|
|
|
GROUP BY package_id;
|