blob: 6ee0588dced94b0757c2e8330b5d083a559bff58 [file]
-- Cursor cost reconciliation queries
-- Run against the lake database after a full billing-cycle event backfill.
--
-- Note: SUM(charged_cents) from events only reconciles with /teams/spend when
-- ALL usage events for the billing cycle are collected (paginate filtered-usage-events).
-- Team-level rollup comparison
SELECT
ROUND(SUM(spend_cents) / 100, 2) AS spend_usd,
ROUND(SUM(included_spend_cents) / 100, 2) AS included_usd,
ROUND(SUM(spend_cents + included_spend_cents) / 100, 2) AS total_cycle_usd
FROM _tool_cursor_user_spend;
SELECT
ROUND(SUM(charged_cents) / 100, 2) AS event_charged_usd,
ROUND(SUM(total_cents) / 100, 2) AS event_model_usd,
COUNT(*) AS event_count,
MIN(event_time) AS earliest_event,
MAX(event_time) AS latest_event
FROM _tool_cursor_usage_events;
-- Per-user: billing cycle spend vs event charged (since billing cycle start)
SELECT
s.email,
ROUND(s.spend_cents / 100, 2) AS spend_usd,
ROUND(s.included_spend_cents / 100, 2) AS included_usd,
ROUND((s.spend_cents + s.included_spend_cents) / 100, 2) AS total_cycle_usd,
ROUND(COALESCE(SUM(e.charged_cents), 0) / 100, 2) AS event_charged_usd,
COUNT(e.event_id) AS event_count
FROM _tool_cursor_user_spend s
LEFT JOIN _tool_cursor_usage_events e
ON s.email = e.user_email
AND e.event_time >= s.billing_cycle_start
GROUP BY s.email, s.spend_cents, s.included_spend_cents
ORDER BY total_cycle_usd DESC;
-- Users with events but no spend row (should be empty)
SELECT DISTINCT e.user_email
FROM _tool_cursor_usage_events e
LEFT JOIN _tool_cursor_user_spend s ON e.user_email = s.email
WHERE s.email IS NULL;