Invoices & Revenue

Invoice entity lifecycle, PaymentTransaction tracking, revenue dashboard (MRR/ARR/Churn), multi-currency support, and export formats.

The invoicing system tracks every payment event as an immutable Invoice record with one or more InvoiceLineItems and a corresponding PaymentTransaction. Invoices are created automatically by the Stripe webhook handler on successful payments. The revenue dashboard aggregates invoice data into MRR, ARR, churn rate, and edition-level analytics.

Invoice Entity

An Invoice represents a billing event for a tenant. It is created by the Stripe webhook handler when a payment succeeds or a subscription renews.

FieldTypeDescription
IdGuidPrimary key
TenantIdGuidTenant this invoice belongs to
SubscriptionIdGuid?Linked TenantSubscription (nullable for manual/one-off invoices)
InvoiceNumberstring(50)Human-readable auto-generated (e.g. INV-2026-00001)
SequenceNumberintAuto-incrementing DB sequence for atomic InvoiceNumber generation
CurrencyCurrencyISO currency code (USD, EUR, SAR, etc.)
SubTotaldecimal(18,2)Pre-discount amount (sum of line items)
DiscountAmountdecimal(18,2)Promotion discount applied
TaxAmountdecimal(18,2)Tax charged (if applicable)
Totaldecimal(18,2)Final billed: SubTotal − DiscountAmount + TaxAmount
StatusInvoiceStatusDraft | Pending | Paid | Void | Refunded
DueDateDateTime?Payment due date (null = immediate)
PaidAtDateTime?When the invoice was paid
BillingCycleBillingCycleThe billing cycle this invoice covers (Monthly, Yearly, etc.)
StripeInvoiceIdstring?Stripe invoice ID for reconciliation (in_xxx)
StripePaymentIntentIdstring?Stripe payment intent ID for tracking (pi_xxx)
PdfUrlstring?URL/path to the generated PDF invoice
Notesstring?Admin notes (internal only — never exposed to tenants)

Invoice Line Items

Each Invoice contains one or more InvoiceLineItems. A line item represents a single billable unit — typically the subscription price for a billing cycle, a promo discount, or a manual adjustment.

FieldTypeDescription
DescriptionstringHuman-readable line item label
QuantityintNumber of units (usually 1)
UnitPricedecimal(18,2)Price per unit
Totaldecimal(18,2)Quantity × UnitPrice
TypeLineItemTypeSubscription | Discount | Tax | Adjustment

PaymentTransaction Entity

A PaymentTransaction records the raw payment event from the gateway. It is linked to an Invoice and captures the gateway-specific transaction ID, the exact amount charged, the currency, and the processing status.

FieldTypeDescription
InvoiceIdGuidLinked invoice
TenantIdGuidTenant that was charged
GatewayPaymentGatewayStripe | PayPal | Paymob | Manual
GatewayTransactionIdstringStripe Payment Intent ID or Charge ID
Amountdecimal(18,2)Amount charged
CurrencyCurrencyCurrency of the charge
StatusTransactionStatusPending | Succeeded | Failed | Refunded
FailureReasonstring?Gateway failure message
GatewayResponsestring?Full JSON response (for debugging)
ProcessedAtDateTime?When the payment was processed
RefundedAtDateTime?When the refund was processed

Invoice Status Lifecycle

Invoices move through a linear lifecycle from creation to settlement or cancellation.

Draft
issued
Pending
payment succeeds
Paid
Void
Refunded

Invoice Numbering

Invoice numbers follow the pattern INV-YYYY-NNNNN. The sequence is maintained per-tenant using IgnoreQueryFilters() to ensure soft-deleted invoices are included in the sequence count, preventing gaps in numbering for audit purposes.

Revenue Dashboard

The billing dashboard aggregates invoice data into 8 key performance indicators. It is accessible at GET /api/v1/billing/dashboard and requires the billing.view permission.

Dashboard KPIs

The dashboard provides the following metrics, all computed from the Invoice and TenantSubscription tables:

  • MRR (Monthly Recurring Revenue) — Sum of all active monthly subscriptions
  • ARR (Annual Recurring Revenue) — MRR × 12
  • Total Revenue — All-time sum of paid invoices
  • Churn Rate — Percentage of subscriptions cancelled in the last 30 days
  • Active Subscriptions — Count of currently active tenants
  • Trial Subscriptions — Count of tenants in trial phase
  • Cancelled This Month — Count of cancellations in current month
  • Platform Health Score — Composite score based on MRR trend, churn, and trial conversion

Multi-Currency Support

SCRIPE supports 28 Stripe-supported currencies. Each Invoice stores the Currency (ISO code), SubTotal, DiscountAmount, TaxAmount, and Total in the original currency. ExchangeRateToUsd and TotalAmountUsd fields normalize amounts for consistent USD-based reporting across all currencies.

Currency GroupExamplesStripe Handling
Standard (×100 to cents)USD, EUR, GBP, SAR, AED, EGPAmount multiplied by 100
Zero-decimalJPY, KWD, BHDAmount passed as-is
3-decimalOMR, TNDAmount multiplied by 1000

Export Formats

The subscription export system (GET /api/v1/subscriptions/export) generates comprehensive reports in three formats.

  • CSV — Lightweight, importable into any spreadsheet or BI tool
  • XLSX — Professional Excel workbook with styled headers, filter metadata sheet, conditional formatting, and auto-sized columns (ClosedXML)
  • PDF — Print-ready document with branded cover page, statistical summary, and paginated data tables (QuestPDF)

API Endpoints

Invoice endpoints are exposed through the InvoicesController and the BillingController:

MethodEndpointDescriptionAuth
GET/api/v1/invoicesList invoices with pagination and filters (status, tenant, date range)🔒 Required
GET/api/v1/invoices/{id}Get invoice details including line items🔒 Required
GET/api/v1/invoices/{id}/pdfDownload invoice as PDF🔒 Required
GET/api/v1/billing/dashboardGet revenue dashboard (MRR, ARR, churn, trends)🔒 Required
GET/api/v1/subscriptions/exportExport subscriptions as CSV, Excel, or PDF🔒 Required