Skip to content

fix(admin): devpass chart uses paid amount, nets refunds - #2225

Merged
smakosh merged 2 commits into
mainfrom
fix/admin-devpass-revenue-chart
May 9, 2026
Merged

smakosh merged 2 commits into
mainfrom
fix/admin-devpass-revenue-chart

Conversation

@smakosh

@smakosh smakosh commented May 9, 2026 •

Copy link
Copy Markdown
Member

Summary

The DevPass admin "revenue & usage" chart was over-reporting revenue and silently dropping all pre-rename history. Stripe MRR shows ~$500 from Aug→Nov 2025, dipping to ~$0 through April, then jumping to $1,762 in May, while the admin chart's "All time" line was flat for months and totaled ~3× the actual revenue.

Two bugs in the timeseries handler at apps/api/src/routes/admin.ts:

  • Sums the wrong column. Revenue used SUM(transaction.creditAmount), but creditAmount on dev_plan_* rows is the credits limit (price × DEV_PLAN_CREDITS_MULTIPLIER, default 3) — not dollars paid. Switched to SUM(transaction.amount), which is set to session.amount_total / 100 (or invoice.amount_paid / 100) on every revenue-bearing insert.
  • Legacy subscription_* rows had no creditAmount. The pre-rename insert paths in apps/api/src/stripe.ts only set amount, so even though the legacy filter matches them, they contributed $0 to the chart. Switching to amount fixes this too — that's why the chart was flat through Jan/Feb/Mar despite Stripe showing real subscribers.

Also nets out refunds: credit_refund rows are joined to their original transaction via relatedTransactionId, scoped to dev plan / (legacy + personal-org) subscription rows, and subtracted from the matching day's revenue.

Test plan

  • Open /devpass in admin — confirm the "All time" range now extends back to the earliest legacy subscription_start (personal org) and chart shows non-zero revenue in Aug–Nov 2025
  • Confirm "Revenue" total roughly matches Stripe's cumulative subscription revenue (was ~3× too high)
  • Confirm a refunded dev plan transaction reduces that day's revenue rather than leaving the gross figure
  • Apply from/to filters and verify the same numbers hold for narrower ranges

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved DevPass revenue reporting accuracy by using actual paid transaction amounts instead of credits.
    • Revenue calculations now properly account for refunds in timeseries data.

Review Change Stack

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 9, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

The PR updates the DevPass timeseries admin endpoint to compute revenue using actual paid dollars instead of credits and adds a daily refunds aggregation. A new self-join query calculates per-day refund totals from credit_refund transactions, which are then subtracted from daily revenue totals.

Changes

DevPass Timeseries Revenue and Refunds

Layer / File(s) Summary
Database Query Support
apps/api/src/routes/admin.ts
Added aliasedTable import (line 10) to enable self-join syntax in refunds query.
Daily Revenue Aggregation
apps/api/src/routes/admin.ts
Switched revenue aggregation from transaction.creditAmount to transaction.amount (cast to NUMERIC) to compute paid dollars per day (lines 8155–8163).
Daily Refunds Query
apps/api/src/routes/admin.ts
Added refundsPerDay query that self-joins credit_refund rows to originating transactions via relatedTransactionId, filters to DevPass types and legacy personal-org behavior, and groups by refund date (lines 8189–8228).
Refund Map Construction
apps/api/src/routes/admin.ts
Built refundMap lookup from refundsPerDay results for per-day refund value access (lines 8275–8278).
Net Revenue Computation
apps/api/src/routes/admin.ts
Updated per-day revenue calculation to subtract refundMap value from daily revenue (line 8309).

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • theopenco/llmgateway#2220: Adds the /devpass/timeseries route that is modified here to use transaction.amount and include daily refund logic.
  • theopenco/llmgateway#2223: Also modifies DevPass timeseries logic in the same file, adjusting routing and transaction type filtering.
  • theopenco/llmgateway#2085: Affects DevPass billing and revenue metrics that are now computed differently by this PR's revenue and refund changes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: fixing the DevPass chart to use paid amount (transaction.amount) instead of credits and accounting for refunds in the revenue calculation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/admin-devpass-revenue-chart

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@smakosh smakosh self-assigned this May 9, 2026
@smakosh
smakosh enabled auto-merge May 9, 2026 14:00

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/api/src/routes/admin.ts (1)

8152-8315: 🏗️ Heavy lift

Add a focused regression test for legacy revenue plus refunds.

This query now depends on three subtle cases at once: current DevPass charges using amount, legacy personal-org subscription charges, and credit_refund rows linked back through relatedTransactionId. A route-level fixture covering those cases would make this much harder to regress.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/routes/admin.ts` around lines 8152 - 8315, Add a focused
regression test that covers (1) a current DevPass charge using
transaction.amount, (2) a legacy subscription charge on a personal org
(LEGACY_DEV_PLAN_TX_TYPES with tables.organization.isPersonal = true), and (3) a
credit_refund row that links back via relatedTransactionId so refunds are netted
out; create route-level fixtures that insert one of each transaction on the same
date (use DEV_PLAN_TX_TYPES, LEGACY_DEV_PLAN_TX_TYPES, and a transaction with
type "credit_refund" whose relatedTransactionId points to one of the originals),
call the admin revenue endpoint (the logic computing revenuePerDay/refundsPerDay
and the date loop in admin.ts), and assert the returned per-day revenue equals
SUM(amounts of completed dev/legacy rows) minus the credit_refund.amount, with
cost unchanged—this ensures revenuePerDay, refundsPerDay, and the netting logic
are covered and prevents regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/api/src/routes/admin.ts`:
- Around line 8152-8315: Add a focused regression test that covers (1) a current
DevPass charge using transaction.amount, (2) a legacy subscription charge on a
personal org (LEGACY_DEV_PLAN_TX_TYPES with tables.organization.isPersonal =
true), and (3) a credit_refund row that links back via relatedTransactionId so
refunds are netted out; create route-level fixtures that insert one of each
transaction on the same date (use DEV_PLAN_TX_TYPES, LEGACY_DEV_PLAN_TX_TYPES,
and a transaction with type "credit_refund" whose relatedTransactionId points to
one of the originals), call the admin revenue endpoint (the logic computing
revenuePerDay/refundsPerDay and the date loop in admin.ts), and assert the
returned per-day revenue equals SUM(amounts of completed dev/legacy rows) minus
the credit_refund.amount, with cost unchanged—this ensures revenuePerDay,
refundsPerDay, and the netting logic are covered and prevents regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4b766438-b706-41ab-aa5e-788666ce83e7

📥 Commits

Reviewing files that changed from the base of the PR and between a18534a and 78b8918.

📒 Files selected for processing (1)
  • apps/api/src/routes/admin.ts

@smakosh
smakosh added this pull request to the merge queue May 9, 2026
Merged via the queue into main with commit 5a35241 May 9, 2026
11 checks passed
@smakosh
smakosh deleted the fix/admin-devpass-revenue-chart branch May 9, 2026 14:19
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