Skip to content

feat(analytics): add revenue-by-currency report - #1843

Merged
github-actions[bot] merged 2 commits into
Smartdevs17:mainfrom
retkatmun:feat/revenue-by-currency-1757
Oct 19, 2026
Merged

github-actions[bot] merged 2 commits into
Smartdevs17:mainfrom
retkatmun:feat/revenue-by-currency-1757

Conversation

@retkatmun

Copy link
Copy Markdown
Contributor

Closes #1757

Summary

Multi-currency revenue is now grouped per currency with monthly/annual totals, subscription counts, averages, and percentage shares. Reports are exportable as CSV or JSON via a new HTTP endpoint.

Changes

New files:

File Purpose
backend/services/analytics/revenueByCurrencyReport.ts Core service: generateReport() groups subscriptions by currency, computing per-currency MRR, ARR, average, and percentage. toMonthlyEquivalent() normalises billing cycles (monthly/yearly/weekly/custom). exportReport() produces CSV (with totals row) or pretty-printed JSON.
backend/services/analytics/revenueByCurrencyRouter.ts Plain Node.js HTTP router. `GET /reports/revenue-by-currency?merchantId=…&format=csv
backend/services/analytics/__tests__/revenueByCurrencyReport.test.ts 27 unit tests covering all paths.

Modified:

  • backend/server.ts — wires the service and router; route placed before the 404 fallback.

Design decisions

  • Decoupled from data layer. The service accepts SubscriptionRevenueInput[] — a minimal shape with amount, currency, billingCycle, and optional status. This maps to both the frontend Subscription.price and backend Subscription.amount without coupling to either.
  • Billing cycle normalisation. toMonthlyEquivalent() converts yearly (÷12), weekly (×52/12), and custom/unknown (as-is) to a monthly equivalent so all currencies are comparable.
  • CSV with totals row. The CSV export includes a header row, one row per currency, then a totals row — suitable for spreadsheet import.
  • Currency normalisation. Currency codes are uppercased and grouped (e.g. "usd" and "USD" are the same group).
  • Status filtering. Only active subscriptions (or those with no status) are included; paused and cancelled are excluded.

Acceptance criteria (from issue)

  • Per-currency totals — each currency gets MRR, ARR, count, average, and percentage
  • Exportable — CSV and JSON formats via ?format= query parameter
  • Tested — 27 unit tests, all passing

Testing

npx jest --config jest.backend.config.js \
  --testMatch '**/backend/services/analytics/__tests__/revenueByCurrencyReport.test.ts'

Test Suites: 1 passed
Tests:       27 passed, 0 failed

Covers: toMonthlyEquivalent() for all billing cycles, generateReport() (empty input, status filtering, single/multi-currency, percentage calculation, sorting, currency normalisation, billing cycle normalisation), exportReport() JSON round-trip, CSV headers/rows/totals/escaping.

retkatmun and others added 2 commits October 19, 2026 17:48
Implements issue Smartdevs17#1757. Revenue is now grouped per currency with
monthly/annual totals, subscription counts, averages, and percentage
shares. Reports are exportable as CSV or JSON.

New files
  backend/services/analytics/revenueByCurrencyReport.ts
    - RevenueByCurrencyReportService: generateReport() groups subscriptions
      by currency, computes per-currency MRR/ARR/average/percentage
    - toMonthlyEquivalent(): normalises billing cycles to monthly
      (monthly/yearly/weekly/custom)
    - exportReport(): CSV (with totals row) or pretty-printed JSON
    - Accepts SubscriptionRevenueInput[] — maps to both frontend
      Subscription.price and backend Subscription.amount

  backend/services/analytics/revenueByCurrencyRouter.ts
    - GET /reports/revenue-by-currency?merchantId=…&format=csv|json
    - CSV responses use text/csv with Content-Disposition for download
    - Injectable SubscriptionProvider for testability

  backend/services/analytics/__tests__/revenueByCurrencyReport.test.ts
    - 27 unit tests; all passing

Modified
  backend/server.ts — wires the service and router; route placed before
    the 404 fallback

Closes Smartdevs17#1757
@drips-wave

drips-wave Bot commented Oct 19, 2026

Copy link
Copy Markdown

@retkatmun Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@github-actions
github-actions Bot merged commit a0d27e2 into Smartdevs17:main Oct 19, 2026
11 of 30 checks passed
@retkatmun
retkatmun deployed to security-review October 19, 2026 16:57 — with GitHub Actions Active

This branch was successfully deployed

1 active deployment
security-review — 888d367e Deployed Oct 19, 2026 by retkatmun via Security Dashboard #1396
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.

Add revenue-by-currency report

1 participant