Skip to content

ads: /ads/earnings — spend & earnings dashboard + PDF report - #104

Merged
ralyodio merged 1 commit into
masterfrom
ads/earnings-page
Jul 17, 2026
Merged

ralyodio merged 1 commit into
masterfrom
ads/earnings-page

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

What

A new /ads/earnings page: a unified money view for the account (a single user is both an advertiser and a publisher), plus a downloadable PDF report to hand an accountant / marketing / exec.

Shows:

  • Tiles: Total earned · Total spend · Net · Available to withdraw (+ Earned/Spent today, Withdrawn).
  • Chart: spend vs. earnings over the last 30 days (recharts).
  • Tables: earnings by site (publisher) and spend by campaign (advertiser), each with impressions/clicks/CTR; plus payout history.
  • PDF report: self-contained, print-friendly (summary tables + inline-SVG chart + payouts).

Linked from Earnings & reports buttons on /ads and /ads/slots.

How

  • Migration ad_slot_daily_series(days) — publisher earnings by day, a server-side aggregate mirroring the existing ad_campaign_daily_series (RLS-scoped, avoids PostgREST's 1000-row cap).
  • lib/ads/series.ts — getSlotDailySeries + mergeMoneySeries (account-wide spend/earn axis).
  • lib/ads/earnings-data.ts — loadEarnings(): one RLS-scoped money model shared by the page and the PDF route. Spend = ad_campaigns.total_spent_cents + stats; earnings = ad_ledger publisher_accrual (authoritative) + ad_slot_stats; payouts; available = earned − non-failed payouts.
  • PDF reuses the existing worker Playwright /pdf endpoint — it just gained an html branch that renders a complete HTML document as-is. No new PDF dependency; recharts was already a dep.

⚠️ Apply the migration by hand

Prod migration history has diverged — apply supabase/migrations/20260717150000_ad_slot_daily_series_rpc.sql via psql over the pooler after merge, or the earnings chart falls back to zero-filled (page still renders; the RPC error is swallowed).

Verified

  • tsc (app + worker) clean · next build compiles /ads/earnings + /api/ads/earnings/pdf.
  • Rendered the PDF report HTML from a sample model — all sections present, $ amounts correct, inline SVG chart, no undefined/NaN (6.2 KB doc).

Note

The PDF route 500s if WORKER_URL isn't set in the environment (same as the existing audit PDF route) — it's set in prod.

🤖 Generated with Claude Code

A unified money page for the account (a single user is both advertiser and
publisher): total earned, total spend, net, available to withdraw; a
spend-vs-earnings chart; per-site earnings and per-campaign spend tables; and
payout history. Plus a downloadable PDF report for an accountant/exec.

- migration: ad_slot_daily_series(days) RPC — publisher earnings by day
  (mirror of ad_campaign_daily_series; server-side aggregate, RLS-scoped)
- lib/ads/series.ts: getSlotDailySeries + mergeMoneySeries
- lib/ads/earnings-data.ts: loadEarnings() — one RLS-scoped money model shared
  by the page and the PDF route (spend from ad_campaigns/stats, earnings from
  ad_ledger publisher_accrual + ad_slot_stats, payouts, merged daily series)
- app/(app)/ads/earnings/page.tsx: tiles, recharts chart (dynamic), tables
- components/ads/money-trend.tsx: recharts spend-vs-earnings line chart
- lib/ads/earnings-report.ts: self-contained print HTML (inline-SVG chart)
- app/api/ads/earnings/pdf/route.ts: renders the report via the worker /pdf
- worker/index.ts: /pdf gains an `html` branch (render raw HTML as-is)
- components/ads/earnings-pdf-button.tsx + nav links from /ads and /ads/slots

No new deps (recharts already present; PDF via the existing worker pipeline).
Migration must be applied to prod by hand (psql over pooler) per the divergence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit 0793673 into master Jul 17, 2026
8 checks passed
@ralyodio
ralyodio deleted the ads/earnings-page branch July 17, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant