billing

package
v0.0.0-...-363cbd8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2025 License: AGPL-3.0 Imports: 21 Imported by: 0

README

DictaMesh Billing System

Overview

The DictaMesh Billing System is a comprehensive, enterprise-grade billing solution designed to handle subscription management, usage-based billing, invoicing, and payment processing for the DictaMesh platform.

Features

Flexible Subscription Management

  • Multiple pricing tiers (Free, Starter, Professional, Enterprise)
  • Monthly and annual billing cycles
  • Seat-based pricing
  • Custom pricing overrides for enterprise deals

Usage-Based Billing

  • Real-time metrics collection via Prometheus
  • Multiple metric types (API calls, storage, data transfer, query processing)
  • Fractional pricing with 6 decimal precision
  • Hourly usage aggregation

Advanced Pricing

  • Tiered pricing for volume discounts
  • Prorated billing for mid-cycle changes
  • Account credits and promotions
  • Tax calculation support

Automated Invoicing

  • Automatic invoice generation
  • Detailed line items
  • PDF generation
  • Multi-currency support

Payment Processing

  • Stripe integration
  • Multiple payment methods
  • Automatic payment retry
  • Webhook handling

Notifications

  • Integration with DictaMesh notification system
  • Email notifications for all billing events
  • Customizable templates
  • Multi-channel delivery

Event-Driven Architecture

  • Kafka event publishing
  • Subscription lifecycle events
  • Payment events
  • Usage threshold alerts

Observability

  • Prometheus metrics
  • OpenTelemetry distributed tracing
  • Comprehensive audit logging
  • Real-time monitoring dashboards

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                    BILLING SYSTEM ARCHITECTURE                   │
└─────────────────────────────────────────────────────────────────┘

┌──────────────────────┐      ┌──────────────────────┐
│   Usage Collector    │      │  Subscription Mgmt   │
│   • Prometheus       │      │  • Plans & tiers     │
│   • Metrics agg      │      │  • Lifecycle mgmt    │
└──────────┬───────────┘      └──────────┬───────────┘
           │                             │
           ▼                             ▼
┌────────────────────────────────────────────────────┐
│          PRICING CALCULATION ENGINE                │
│  • Rate cards         • Tiered pricing             │
│  • Fractional calc    • Proration                  │
└────────────────────┬───────────────────────────────┘
                     │
                     ▼
┌────────────────────────────────────────────────────┐
│          INVOICE GENERATION                        │
│  • Line items         • PDF generation             │
└────────────────────┬───────────────────────────────┘
                     │
        ┌────────────┼────────────┐
        │            │            │
        ▼            ▼            ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│  Payment    │ │ Notification│ │   Event     │
│  (Stripe)   │ │   Service   │ │    Bus      │
└─────────────┘ └─────────────┘ └─────────────┘

Package Structure

pkg/billing/
├── types.go              # Core type definitions
├── config.go             # Configuration management
├── models/
│   └── models.go         # GORM database models
├── pricing.go            # Pricing calculation engine
├── metrics.go            # Usage metrics collection
├── invoice.go            # Invoice generation
├── payment.go            # Payment processing (Stripe)
├── notifications.go      # Notification integration
├── events.go             # Kafka event publishing
├── observability.go      # Prometheus & OpenTelemetry
└── README.md            # This file

Database Schema

Core Tables
  • dictamesh_billing_organizations - Billing accounts
  • dictamesh_billing_subscription_plans - Product catalog
  • dictamesh_billing_subscriptions - Active subscriptions
  • dictamesh_billing_usage_metrics - Time-series usage data (partitioned)
  • dictamesh_billing_invoices - Generated invoices
  • dictamesh_billing_invoice_line_items - Invoice charges
  • dictamesh_billing_payments - Payment transactions
  • dictamesh_billing_pricing_tiers - Volume-based pricing
  • dictamesh_billing_credits - Account credits
  • dictamesh_billing_audit_log - Comprehensive audit trail

Usage Examples

Initialize the Billing System
import (
    "github.com/dictamesh/dictamesh/pkg/billing"
)

// Load configuration
config, err := billing.LoadFromEnv()
if err != nil {
    log.Fatal(err)
}

// Create services
pricingEngine := billing.NewPricingEngine(config)
metricsCollector := billing.NewMetricsCollector(db, config)
invoiceService := billing.NewInvoiceService(db, config, pricingEngine, metricsCollector)
paymentService := billing.NewPaymentService(db, config, invoiceService)
notificationService := billing.NewNotificationService(config)
Create a Subscription
subscription := &models.Subscription{
    OrganizationID:     orgID,
    PlanID:             planID,
    Status:             "active",
    CurrentPeriodStart: time.Now(),
    CurrentPeriodEnd:   time.Now().AddDate(0, 1, 0),
    Quantity:           5, // 5 seats
}

if err := db.Create(subscription).Error; err != nil {
    return err
}

// Publish event
eventPublisher.PublishSubscriptionCreated(ctx, subscription)
Record Usage Metrics
// Record API call
metricsCollector.RecordAPICall(organizationID, "/graphql", "POST")

// Record storage
metricsCollector.RecordStorage(organizationID, "metadata", 50*1024*1024*1024) // 50GB

// Record data transfer
metricsCollector.RecordTransfer(organizationID, "out", 1024*1024*1024) // 1GB
Generate an Invoice
invoice, err := invoiceService.GenerateInvoice(ctx, subscriptionID)
if err != nil {
    return err
}

// Send notification
notificationService.SendInvoiceCreatedNotification(ctx, invoice)

// Publish event
eventPublisher.PublishInvoiceCreated(ctx, invoice)
Process a Payment
payment, err := paymentService.ChargeInvoice(ctx, invoiceID)
if err != nil {
    // Handle payment failure
    notificationService.SendPaymentFailedNotification(ctx, payment, invoice)
    eventPublisher.PublishPaymentFailed(ctx, payment)
    return err
}

// Payment succeeded
notificationService.SendPaymentSucceededNotification(ctx, payment, invoice)
eventPublisher.PublishPaymentSucceeded(ctx, payment)
Calculate Pricing
// Fetch usage for billing period
usage, err := metricsCollector.GetUsageForPeriod(ctx, orgID, periodStart, periodEnd)

// Fetch credits
var credits []models.Credit
db.Where("organization_id = ? AND status = ?", orgID, "active").Find(&credits)

// Calculate charges
calc, err := pricingEngine.CalculateSubscriptionCharge(
    subscription,
    plan,
    usage,
    credits,
)

// calc.Total contains the final amount
// calc.LineItems contains itemized charges

Configuration

Configure the billing system via environment variables:

# Database
BILLING_DATABASE_DSN=postgres://user:pass@localhost/dictamesh

# Stripe
STRIPE_API_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_ENABLED=true

# Invoice Settings
INVOICE_DUE_DAYS=30
INVOICE_NUMBER_PREFIX=INV-
INVOICE_TAX_RATE=0.10
INVOICE_DEFAULT_CURRENCY=USD

# Usage Metrics
USAGE_AGGREGATION_INTERVAL=1h
USAGE_RETENTION_DAYS=90
USAGE_ENABLE_REALTIME=true

# Notifications
NOTIFICATION_SERVICE_URL=http://localhost:8080
NOTIFICATION_RETRY_ATTEMPTS=3

# Feature Flags
FEATURE_AUTO_PAYMENT=true
FEATURE_USAGE_METRICS=true
FEATURE_TIERED_PRICING=true
FEATURE_CREDITS=true

Subscription Plans

Default Plans
Plan Price API Calls Storage Transfer Adapters
Free $0/mo 10K 1GB 1GB 1
Starter $99/mo 1M 50GB 100GB 5
Professional $499/mo 10M 500GB 1TB 25
Enterprise $2,499/mo 100M 5TB 10TB Unlimited
Overage Pricing
  • API Calls: $0.01 - $0.000001 per 1K calls (volume discounts)
  • Storage: $0.50 - $0.10 per GB (volume discounts)
  • Transfer: $0.50 - $0.10 per GB (volume discounts)
  • Additional Seats: $49 - $199 per seat (plan-dependent)

Metrics

Prometheus Metrics
# Subscriptions
dictamesh_billing_active_subscriptions{plan="professional"} 150

# Revenue
dictamesh_billing_mrr 74850.00
dictamesh_billing_arr 898200.00

# Invoices
dictamesh_billing_invoices_generated_total{status="paid"} 1234

# Payments
dictamesh_billing_payments_processed_total{status="succeeded",provider="stripe"} 987
dictamesh_billing_payment_failures_total{failure_code="card_declined"} 23
Events
billing.subscription.created
billing.subscription.updated
billing.subscription.canceled
billing.invoice.created
billing.invoice.paid
billing.invoice.overdue
billing.payment.succeeded
billing.payment.failed
billing.usage.threshold_reached
billing.credit.applied

Notification Templates

Available Templates
  1. billing_invoice_generated - New invoice created
  2. billing_payment_succeeded - Payment confirmation
  3. billing_payment_failed - Payment failure alert
  4. billing_invoice_overdue - Overdue invoice notice
  5. billing_subscription_created - Welcome email
  6. billing_subscription_canceled - Cancellation confirmation
  7. billing_usage_threshold_reached - Usage alert
  8. billing_upcoming_renewal - Renewal reminder

API Integration

REST API Endpoints
# Organizations
POST   /api/v1/billing/organizations
GET    /api/v1/billing/organizations/:id
PUT    /api/v1/billing/organizations/:id

# Subscriptions
POST   /api/v1/billing/subscriptions
GET    /api/v1/billing/subscriptions/:id
POST   /api/v1/billing/subscriptions/:id/cancel

# Invoices
GET    /api/v1/billing/invoices
GET    /api/v1/billing/invoices/:id
GET    /api/v1/billing/invoices/:id/pdf

# Payments
POST   /api/v1/billing/payments
GET    /api/v1/billing/payments/:id
POST   /api/v1/billing/payment-methods

# Usage
GET    /api/v1/billing/usage/current
GET    /api/v1/billing/usage/history

Security

Best Practices
  • ✅ Never store raw card numbers (use Stripe tokens)
  • ✅ All payment data encrypted at rest and in transit
  • ✅ PCI DSS compliant payment processing
  • ✅ Webhook signature verification
  • ✅ Role-based access control
  • ✅ Comprehensive audit logging
  • ✅ Rate limiting on billing APIs
Webhook Verification
// Verify Stripe webhook signature
stripe.Key = config.Stripe.APIKey

event, err := webhook.ConstructEvent(
    payload,
    signature,
    config.Stripe.WebhookSecret,
)

Testing

Unit Tests
go test ./pkg/billing/...
Integration Tests
go test -tags=integration ./pkg/billing/...
Test Coverage
go test -cover ./pkg/billing/...

Deployment

Database Migration
# Run migrations
migrate -path pkg/database/migrations/sql \
        -database postgres://localhost/dictamesh up

# Rollback
migrate -path pkg/database/migrations/sql \
        -database postgres://localhost/dictamesh down 1
Docker Deployment
# Build
docker build -t dictamesh-billing .

# Run
docker run -p 8080:8080 \
  -e BILLING_DATABASE_DSN=... \
  -e STRIPE_API_KEY=... \
  dictamesh-billing

Monitoring

Grafana Dashboards

Import the provided Grafana dashboard to monitor:

  • Monthly Recurring Revenue (MRR)
  • Active Subscriptions
  • Payment Success Rate
  • Invoice Aging
  • Usage Trends
Alerts

Configure alerts for:

  • Payment failure rate > 5%
  • Invoice collection rate < 95%
  • Unusual usage spikes
  • Credit balance alerts

Troubleshooting

Common Issues

Q: Invoices not generating

  • Check subscription period_end dates
  • Verify usage metrics are being collected
  • Check invoice generation cron job

Q: Payments failing

  • Verify Stripe API keys
  • Check webhook endpoint configuration
  • Review payment method status

Q: Usage metrics missing

  • Verify Prometheus scraping configuration
  • Check metrics aggregation worker
  • Review database partitions

Contributing

See CONTRIBUTING.md for guidelines.

License

SPDX-License-Identifier: AGPL-3.0-or-later Copyright (C) 2025 Controle Digital Ltda

Support

For issues and questions:

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RecordSpanError

func RecordSpanError(span trace.Span, err error)

RecordSpanError records an error in the current span

func RecordSpanSuccess

func RecordSpanSuccess(span trace.Span)

RecordSpanSuccess records success in the current span

func TraceInvoiceGeneration

func TraceInvoiceGeneration(ctx context.Context, subscriptionID string) (context.Context, trace.Span)

TraceInvoiceGeneration creates a span for invoice generation

func TraceNotificationSend

func TraceNotificationSend(ctx context.Context, notificationType, recipientID string) (context.Context, trace.Span)

TraceNotificationSend creates a span for notification sending

func TracePaymentProcessing

func TracePaymentProcessing(ctx context.Context, invoiceID, provider string) (context.Context, trace.Span)

TracePaymentProcessing creates a span for payment processing

func TracePricingCalculation

func TracePricingCalculation(ctx context.Context, subscriptionID string) (context.Context, trace.Span)

TracePricingCalculation creates a span for pricing calculation

func TraceUsageCollection

func TraceUsageCollection(ctx context.Context, organizationID string) (context.Context, trace.Span)

TraceUsageCollection creates a span for usage collection

Types

type BillingConfig

type BillingConfig struct {
	// Database connection
	DatabaseDSN string

	// Payment providers
	StripeAPIKey        string
	StripeWebhookSecret string
	PayPalClientID      string
	PayPalClientSecret  string

	// Invoice settings
	InvoiceDueDays      int
	InvoiceNumberPrefix string
	TaxRate             decimal.Decimal
	DefaultCurrency     string

	// Usage aggregation
	UsageAggregationInterval time.Duration
	UsageRetentionDays       int

	// Notifications
	NotificationServiceURL string

	// Feature flags
	EnableAutoPayment   bool
	EnableUsageMetrics  bool
	EnableTieredPricing bool
	EnableMultiCurrency bool
}

BillingConfig represents the billing system configuration

type BillingCycle

type BillingCycle string

BillingCycle represents the billing frequency

const (
	BillingCycleMonthly BillingCycle = "monthly"
	BillingCycleAnnual  BillingCycle = "annual"
)

type BillingEventPublisher

type BillingEventPublisher struct {
	// contains filtered or unexported fields
}

BillingEventPublisher publishes billing events to Kafka

func NewBillingEventPublisher

func NewBillingEventPublisher(eventBus EventBus) *BillingEventPublisher

NewBillingEventPublisher creates a new event publisher

func (*BillingEventPublisher) PublishCreditApplied

func (p *BillingEventPublisher) PublishCreditApplied(
	ctx context.Context,
	credit *models.Credit,
	invoiceID string,
	amountApplied string,
) error

PublishCreditApplied publishes a credit applied event

func (*BillingEventPublisher) PublishInvoiceCreated

func (p *BillingEventPublisher) PublishInvoiceCreated(
	ctx context.Context,
	invoice *models.Invoice,
) error

PublishInvoiceCreated publishes an invoice created event

func (*BillingEventPublisher) PublishInvoiceOverdue

func (p *BillingEventPublisher) PublishInvoiceOverdue(
	ctx context.Context,
	invoice *models.Invoice,
) error

PublishInvoiceOverdue publishes an invoice overdue event

func (*BillingEventPublisher) PublishInvoicePaid

func (p *BillingEventPublisher) PublishInvoicePaid(
	ctx context.Context,
	invoice *models.Invoice,
	paymentID string,
) error

PublishInvoicePaid publishes an invoice paid event

func (*BillingEventPublisher) PublishPaymentFailed

func (p *BillingEventPublisher) PublishPaymentFailed(
	ctx context.Context,
	payment *models.Payment,
) error

PublishPaymentFailed publishes a payment failed event

func (*BillingEventPublisher) PublishPaymentSucceeded

func (p *BillingEventPublisher) PublishPaymentSucceeded(
	ctx context.Context,
	payment *models.Payment,
) error

PublishPaymentSucceeded publishes a payment succeeded event

func (*BillingEventPublisher) PublishSubscriptionCanceled

func (p *BillingEventPublisher) PublishSubscriptionCanceled(
	ctx context.Context,
	subscription *models.Subscription,
) error

PublishSubscriptionCanceled publishes a subscription canceled event

func (*BillingEventPublisher) PublishSubscriptionCreated

func (p *BillingEventPublisher) PublishSubscriptionCreated(
	ctx context.Context,
	subscription *models.Subscription,
) error

PublishSubscriptionCreated publishes a subscription created event

func (*BillingEventPublisher) PublishUsageThresholdReached

func (p *BillingEventPublisher) PublishUsageThresholdReached(
	ctx context.Context,
	organizationID string,
	metricType MetricType,
	currentUsage, threshold string,
	percentUsed int,
) error

PublishUsageThresholdReached publishes a usage threshold reached event

type BillingReport

type BillingReport struct {
	ReportType  string // mrr, revenue, churn, usage
	PeriodStart time.Time
	PeriodEnd   time.Time
	Data        map[string]interface{}
	GeneratedAt time.Time
}

BillingReport represents various billing reports

type ChargeCalculation

type ChargeCalculation struct {
	BaseCharge   decimal.Decimal
	UsageCharges map[MetricType]decimal.Decimal
	AddonCharges decimal.Decimal
	Subtotal     decimal.Decimal
	Credits      decimal.Decimal
	TaxAmount    decimal.Decimal
	Total        decimal.Decimal
	LineItems    []InvoiceLineItem
}

ChargeCalculation represents the result of pricing calculation

type Config

type Config struct {
	// Database
	DatabaseDSN string

	// Stripe configuration
	Stripe StripeConfig

	// PayPal configuration
	PayPal PayPalConfig

	// Invoice settings
	Invoice InvoiceConfig

	// Usage metrics settings
	Usage UsageConfig

	// Notification settings
	Notifications NotificationConfig

	// Feature flags
	Features FeatureFlags

	// Rate limiting
	RateLimits RateLimitConfig
}

Config represents the billing system configuration

func LoadFromEnv

func LoadFromEnv() (*Config, error)

LoadFromEnv loads configuration from environment variables

func (*Config) Validate

func (c *Config) Validate() error

Validate checks if the configuration is valid

type CreditAppliedEvent

type CreditAppliedEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	CreditID       string    `json:"credit_id"`
	OrganizationID string    `json:"organization_id"`
	InvoiceID      string    `json:"invoice_id"`
	Amount         string    `json:"amount"`
	Currency       string    `json:"currency"`
	Reason         string    `json:"reason"`
}

CreditAppliedEvent represents a credit application event

type CreditStatus

type CreditStatus string

CreditStatus represents the current state of a credit

const (
	CreditStatusActive    CreditStatus = "active"
	CreditStatusExhausted CreditStatus = "exhausted"
	CreditStatusExpired   CreditStatus = "expired"
	CreditStatusVoided    CreditStatus = "voided"
)

type EventBus

type EventBus interface {
	Publish(ctx context.Context, topic string, key string, value interface{}) error
}

EventBus defines the interface for publishing events

type EventType

type EventType string

EventType represents billing event types for Kafka

const (
	EventSubscriptionCreated   EventType = "billing.subscription.created"
	EventSubscriptionUpdated   EventType = "billing.subscription.updated"
	EventSubscriptionCanceled  EventType = "billing.subscription.canceled"
	EventInvoiceCreated        EventType = "billing.invoice.created"
	EventInvoicePaid           EventType = "billing.invoice.paid"
	EventInvoiceOverdue        EventType = "billing.invoice.overdue"
	EventPaymentSucceeded      EventType = "billing.payment.succeeded"
	EventPaymentFailed         EventType = "billing.payment.failed"
	EventUsageThresholdReached EventType = "billing.usage.threshold_reached"
	EventCreditApplied         EventType = "billing.credit.applied"
)

type FeatureFlags

type FeatureFlags struct {
	EnableAutoPayment   bool // Automatically charge payment methods
	EnableUsageMetrics  bool // Track and bill for usage
	EnableTieredPricing bool // Support volume-based pricing tiers
	EnableMultiCurrency bool // Support multiple currencies
	EnableCredits       bool // Support account credits
	EnableProration     bool // Prorate charges for mid-cycle changes
}

FeatureFlags controls which features are enabled

type InvoiceConfig

type InvoiceConfig struct {
	DueDays         int             // Number of days until invoice is due
	NumberPrefix    string          // Prefix for invoice numbers (e.g., "INV-")
	TaxRate         decimal.Decimal // Default tax rate (e.g., 0.10 for 10%)
	DefaultCurrency string          // Default currency code (ISO 4217)
	PDFStoragePath  string          // Path to store generated PDF files
}

InvoiceConfig contains invoice generation settings

type InvoiceCreatedEvent

type InvoiceCreatedEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	InvoiceID      string    `json:"invoice_id"`
	InvoiceNumber  string    `json:"invoice_number"`
	OrganizationID string    `json:"organization_id"`
	SubscriptionID string    `json:"subscription_id"`
	TotalAmount    string    `json:"total_amount"`
	Currency       string    `json:"currency"`
	Status         string    `json:"status"`
	DueDate        time.Time `json:"due_date"`
}

InvoiceCreatedEvent represents an invoice creation event

type InvoiceLineItem

type InvoiceLineItem struct {
	Description string
	Quantity    decimal.Decimal
	UnitPrice   decimal.Decimal
	Amount      decimal.Decimal
	ItemType    LineItemType
	MetricType  MetricType
	PeriodStart *time.Time
	PeriodEnd   *time.Time
	Metadata    map[string]interface{}
}

InvoiceLineItem represents a single charge on an invoice

type InvoiceOverdueEvent

type InvoiceOverdueEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	InvoiceID      string    `json:"invoice_id"`
	InvoiceNumber  string    `json:"invoice_number"`
	OrganizationID string    `json:"organization_id"`
	AmountDue      string    `json:"amount_due"`
	Currency       string    `json:"currency"`
	DueDate        time.Time `json:"due_date"`
	DaysOverdue    int       `json:"days_overdue"`
}

InvoiceOverdueEvent represents an overdue invoice event

type InvoicePaidEvent

type InvoicePaidEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	InvoiceID      string    `json:"invoice_id"`
	InvoiceNumber  string    `json:"invoice_number"`
	OrganizationID string    `json:"organization_id"`
	PaymentID      string    `json:"payment_id"`
	AmountPaid     string    `json:"amount_paid"`
	Currency       string    `json:"currency"`
	PaidAt         time.Time `json:"paid_at"`
}

InvoicePaidEvent represents an invoice payment event

type InvoiceService

type InvoiceService struct {
	// contains filtered or unexported fields
}

InvoiceService handles invoice generation and management

func NewInvoiceService

func NewInvoiceService(
	db *gorm.DB,
	config *Config,
	pricingEngine *PricingEngine,
	metricsCollector *MetricsCollector,
) *InvoiceService

NewInvoiceService creates a new invoice service

func (*InvoiceService) FinalizeInvoice

func (is *InvoiceService) FinalizeInvoice(ctx context.Context, invoiceID string) error

FinalizeInvoice marks an invoice as finalized and ready for payment

func (*InvoiceService) GenerateInvoice

func (is *InvoiceService) GenerateInvoice(
	ctx context.Context,
	subscriptionID string,
) (*models.Invoice, error)

GenerateInvoice generates an invoice for a subscription billing period

func (*InvoiceService) GetInvoice

func (is *InvoiceService) GetInvoice(ctx context.Context, invoiceID string) (*models.Invoice, error)

GetInvoice retrieves an invoice by ID

func (*InvoiceService) GetUpcomingInvoice

func (is *InvoiceService) GetUpcomingInvoice(
	ctx context.Context,
	subscriptionID string,
) (*models.Invoice, error)

GetUpcomingInvoice calculates what the next invoice will look like

func (*InvoiceService) ListInvoices

func (is *InvoiceService) ListInvoices(
	ctx context.Context,
	organizationID string,
	limit, offset int,
) ([]models.Invoice, error)

ListInvoices retrieves invoices for an organization

func (*InvoiceService) MarkInvoiceAsPaid

func (is *InvoiceService) MarkInvoiceAsPaid(
	ctx context.Context,
	invoiceID string,
	paymentID string,
	paidAmount decimal.Decimal,
) error

MarkInvoiceAsPaid marks an invoice as paid

func (*InvoiceService) ProcessOverdueInvoices

func (is *InvoiceService) ProcessOverdueInvoices(ctx context.Context) error

ProcessOverdueInvoices marks overdue invoices and triggers notifications

func (*InvoiceService) VoidInvoice

func (is *InvoiceService) VoidInvoice(ctx context.Context, invoiceID string) error

VoidInvoice voids an invoice

type InvoiceStatus

type InvoiceStatus string

InvoiceStatus represents the current state of an invoice

const (
	InvoiceStatusDraft         InvoiceStatus = "draft"
	InvoiceStatusOpen          InvoiceStatus = "open"
	InvoiceStatusPaid          InvoiceStatus = "paid"
	InvoiceStatusVoid          InvoiceStatus = "void"
	InvoiceStatusUncollectible InvoiceStatus = "uncollectible"
)

type LineItemType

type LineItemType string

LineItemType represents different types of invoice line items

const (
	LineItemTypeSubscriptionBase LineItemType = "subscription_base"
	LineItemTypeUsageAPICalls    LineItemType = "usage_api_calls"
	LineItemTypeUsageStorage     LineItemType = "usage_storage"
	LineItemTypeUsageTransfer    LineItemType = "usage_transfer"
	LineItemTypeAddonSeats       LineItemType = "addon_seats"
	LineItemTypeAddonSupport     LineItemType = "addon_support"
	LineItemTypeCredit           LineItemType = "credit"
	LineItemTypeTax              LineItemType = "tax"
	LineItemTypeDiscount         LineItemType = "discount"
)

type MetricType

type MetricType string

MetricType represents different billable metrics

const (
	MetricTypeAPICalls          MetricType = "api_calls"
	MetricTypeStorageGB         MetricType = "storage_gb"
	MetricTypeTransferGBIn      MetricType = "transfer_gb_in"
	MetricTypeTransferGBOut     MetricType = "transfer_gb_out"
	MetricTypeQuerySeconds      MetricType = "query_seconds"
	MetricTypeGraphQLOperations MetricType = "graphql_operations"
	MetricTypeKafkaEvents       MetricType = "kafka_events"
	MetricTypeAdaptersActive    MetricType = "adapters_active"
)

type MetricsCollector

type MetricsCollector struct {
	// contains filtered or unexported fields
}

MetricsCollector handles usage metrics collection and aggregation

func NewMetricsCollector

func NewMetricsCollector(db *gorm.DB, config *Config) *MetricsCollector

NewMetricsCollector creates a new metrics collector

func (*MetricsCollector) AggregateUsageMetrics

func (mc *MetricsCollector) AggregateUsageMetrics(ctx context.Context) error

AggregateUsageMetrics aggregates Prometheus metrics into database records

func (*MetricsCollector) GetCurrentUsage

func (mc *MetricsCollector) GetCurrentUsage(
	ctx context.Context,
	organizationID string,
) (map[MetricType]decimal.Decimal, error)

GetCurrentUsage retrieves current usage (real-time)

func (*MetricsCollector) GetUsageForPeriod

func (mc *MetricsCollector) GetUsageForPeriod(
	ctx context.Context,
	organizationID string,
	periodStart, periodEnd time.Time,
) (*UsageAggregation, error)

GetUsageForPeriod retrieves aggregated usage for a billing period

func (*MetricsCollector) RecordAPICall

func (mc *MetricsCollector) RecordAPICall(organizationID, endpoint, method string)

RecordAPICall records an API call metric

func (*MetricsCollector) RecordActiveAdapters

func (mc *MetricsCollector) RecordActiveAdapters(organizationID string, count int)

RecordActiveAdapters records the number of active adapters

func (*MetricsCollector) RecordKafkaEvent

func (mc *MetricsCollector) RecordKafkaEvent(organizationID, topic string)

RecordKafkaEvent records a Kafka event

func (*MetricsCollector) RecordQuery

func (mc *MetricsCollector) RecordQuery(organizationID, queryType string, duration time.Duration)

RecordQuery records a query execution

func (*MetricsCollector) RecordStorage

func (mc *MetricsCollector) RecordStorage(organizationID, storageType string, bytes int64)

RecordStorage records current storage usage

func (*MetricsCollector) RecordTransfer

func (mc *MetricsCollector) RecordTransfer(organizationID, direction string, bytes int64)

RecordTransfer records data transfer

func (*MetricsCollector) StartAggregationWorker

func (mc *MetricsCollector) StartAggregationWorker(ctx context.Context)

StartAggregationWorker starts a background worker to aggregate metrics periodically

type Money

type Money struct {
	Amount   decimal.Decimal
	Currency string
}

Money represents a monetary amount with currency

type NotificationConfig

type NotificationConfig struct {
	ServiceURL     string        // URL of the notification service
	RetryAttempts  int           // Number of retry attempts for failed notifications
	RetryDelay     time.Duration // Delay between retry attempts
	TimeoutSeconds int           // Timeout for notification requests
}

NotificationConfig contains notification integration settings

type NotificationRequest

type NotificationRequest struct {
	RecipientID   string                 `json:"recipient_id"`
	RecipientType string                 `json:"recipient_type"`
	TemplateCode  string                 `json:"template_code"`
	Channels      []string               `json:"channels"`
	Priority      string                 `json:"priority"`
	Data          map[string]interface{} `json:"data"`
}

NotificationRequest represents a request to the notification service

type NotificationService

type NotificationService struct {
	// contains filtered or unexported fields
}

NotificationService handles sending billing-related notifications

func NewNotificationService

func NewNotificationService(config *Config) *NotificationService

NewNotificationService creates a new notification service

func (*NotificationService) CreateBillingTemplates

func (ns *NotificationService) CreateBillingTemplates(ctx context.Context) error

CreateBillingTemplates creates email templates for billing notifications This function should be called during system initialization

func (*NotificationService) SendInvoiceCreatedNotification

func (ns *NotificationService) SendInvoiceCreatedNotification(
	ctx context.Context,
	invoice *models.Invoice,
) error

SendInvoiceCreatedNotification sends notification when invoice is created

func (*NotificationService) SendInvoiceOverdueNotification

func (ns *NotificationService) SendInvoiceOverdueNotification(
	ctx context.Context,
	invoice *models.Invoice,
) error

SendInvoiceOverdueNotification sends notification when invoice is overdue

func (*NotificationService) SendPaymentFailedNotification

func (ns *NotificationService) SendPaymentFailedNotification(
	ctx context.Context,
	payment *models.Payment,
	invoice *models.Invoice,
) error

SendPaymentFailedNotification sends notification when payment fails

func (*NotificationService) SendPaymentSucceededNotification

func (ns *NotificationService) SendPaymentSucceededNotification(
	ctx context.Context,
	payment *models.Payment,
	invoice *models.Invoice,
) error

SendPaymentSucceededNotification sends notification when payment succeeds

func (*NotificationService) SendSubscriptionCanceledNotification

func (ns *NotificationService) SendSubscriptionCanceledNotification(
	ctx context.Context,
	subscription *models.Subscription,
) error

SendSubscriptionCanceledNotification sends notification when subscription is canceled

func (*NotificationService) SendSubscriptionCreatedNotification

func (ns *NotificationService) SendSubscriptionCreatedNotification(
	ctx context.Context,
	subscription *models.Subscription,
) error

SendSubscriptionCreatedNotification sends notification when subscription is created

func (*NotificationService) SendUpcomingRenewalNotification

func (ns *NotificationService) SendUpcomingRenewalNotification(
	ctx context.Context,
	subscription *models.Subscription,
	upcomingInvoice *models.Invoice,
) error

SendUpcomingRenewalNotification sends notification before subscription renewal

func (*NotificationService) SendUsageThresholdNotification

func (ns *NotificationService) SendUsageThresholdNotification(
	ctx context.Context,
	organizationID string,
	metricType MetricType,
	currentUsage, threshold string,
	percentUsed int,
) error

SendUsageThresholdNotification sends notification when usage threshold is reached

type ObservabilityService

type ObservabilityService struct{}

ObservabilityService provides observability instrumentation

func NewObservabilityService

func NewObservabilityService() *ObservabilityService

NewObservabilityService creates a new observability service

func (*ObservabilityService) RecordCreditApplied

func (o *ObservabilityService) RecordCreditApplied(reason string)

RecordCreditApplied records a credit application

func (*ObservabilityService) RecordCreditIssued

func (o *ObservabilityService) RecordCreditIssued(reason string)

RecordCreditIssued records a credit issuance

func (*ObservabilityService) RecordInvoiceGenerated

func (o *ObservabilityService) RecordInvoiceGenerated(status string, amount float64, currency string)

RecordInvoiceGenerated records an invoice generation

func (*ObservabilityService) RecordPaymentDuration

func (o *ObservabilityService) RecordPaymentDuration(provider string, seconds float64)

RecordPaymentDuration records payment processing duration

func (*ObservabilityService) RecordPaymentFailure

func (o *ObservabilityService) RecordPaymentFailure(failureCode, provider string)

RecordPaymentFailure records a payment failure

func (*ObservabilityService) RecordPaymentProcessed

func (o *ObservabilityService) RecordPaymentProcessed(status, provider string, amount float64, currency string)

RecordPaymentProcessed records a payment attempt

func (*ObservabilityService) RecordSubscriptionCanceled

func (o *ObservabilityService) RecordSubscriptionCanceled(plan, reason string)

RecordSubscriptionCanceled records a subscription cancellation

func (*ObservabilityService) RecordSubscriptionCreated

func (o *ObservabilityService) RecordSubscriptionCreated(plan string)

RecordSubscriptionCreated records a subscription creation

func (*ObservabilityService) RecordUsageMetricCollected

func (o *ObservabilityService) RecordUsageMetricCollected(metricType string)

RecordUsageMetricCollected records a usage metric collection

func (*ObservabilityService) UpdateARR

func (o *ObservabilityService) UpdateARR(arr float64)

UpdateARR updates the annual recurring revenue metric

func (*ObservabilityService) UpdateMRR

func (o *ObservabilityService) UpdateMRR(mrr float64)

UpdateMRR updates the monthly recurring revenue metric

type OrganizationStatus

type OrganizationStatus string

OrganizationStatus represents the current state of a billing organization

const (
	OrganizationStatusActive    OrganizationStatus = "active"
	OrganizationStatusSuspended OrganizationStatus = "suspended"
	OrganizationStatusDeleted   OrganizationStatus = "deleted"
)

type PayPalConfig

type PayPalConfig struct {
	ClientID     string
	ClientSecret string
	Environment  string // sandbox or production
	Enabled      bool
}

PayPalConfig contains PayPal payment provider settings

type PaymentFailedEvent

type PaymentFailedEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	PaymentID      string    `json:"payment_id"`
	OrganizationID string    `json:"organization_id"`
	InvoiceID      string    `json:"invoice_id"`
	Amount         string    `json:"amount"`
	Currency       string    `json:"currency"`
	FailureCode    string    `json:"failure_code"`
	FailureMessage string    `json:"failure_message"`
	FailedAt       time.Time `json:"failed_at"`
}

PaymentFailedEvent represents a failed payment event

type PaymentMethod

type PaymentMethod struct {
	ID             string
	Type           string // card, ach, paypal, etc.
	Last4          string
	ExpiryMonth    int
	ExpiryYear     int
	Brand          string
	IsDefault      bool
	ProviderID     string // Stripe payment method ID
	OrganizationID string
}

PaymentMethod represents a stored payment method

type PaymentProvider

type PaymentProvider string

PaymentProvider represents payment processing providers

const (
	PaymentProviderStripe PaymentProvider = "stripe"
	PaymentProviderPayPal PaymentProvider = "paypal"
	PaymentProviderManual PaymentProvider = "manual"
)

type PaymentService

type PaymentService struct {
	// contains filtered or unexported fields
}

PaymentService handles payment processing

func NewPaymentService

func NewPaymentService(
	db *gorm.DB,
	config *Config,
	invoiceService *InvoiceService,
) *PaymentService

NewPaymentService creates a new payment service

func (*PaymentService) AttachPaymentMethod

func (ps *PaymentService) AttachPaymentMethod(
	ctx context.Context,
	organizationID, paymentMethodID string,
	setAsDefault bool,
) error

AttachPaymentMethod attaches a payment method to a customer

func (*PaymentService) ChargeInvoice

func (ps *PaymentService) ChargeInvoice(
	ctx context.Context,
	invoiceID string,
) (*models.Payment, error)

ChargeInvoice charges a payment method for an invoice

func (*PaymentService) CreateStripeCustomer

func (ps *PaymentService) CreateStripeCustomer(
	ctx context.Context,
	org *models.Organization,
) (string, error)

CreateStripeCustomer creates a Stripe customer for an organization

func (*PaymentService) HandleWebhook

func (ps *PaymentService) HandleWebhook(
	ctx context.Context,
	provider PaymentProvider,
	eventType string,
	payload map[string]interface{},
) error

HandleWebhook processes payment provider webhooks

func (*PaymentService) ListPayments

func (ps *PaymentService) ListPayments(
	ctx context.Context,
	organizationID string,
	limit, offset int,
) ([]models.Payment, error)

ListPayments retrieves payments for an organization

func (*PaymentService) RefundPayment

func (ps *PaymentService) RefundPayment(
	ctx context.Context,
	paymentID string,
	amount *decimal.Decimal,
) error

RefundPayment refunds a payment

type PaymentStatus

type PaymentStatus string

PaymentStatus represents the current state of a payment

const (
	PaymentStatusPending   PaymentStatus = "pending"
	PaymentStatusSucceeded PaymentStatus = "succeeded"
	PaymentStatusFailed    PaymentStatus = "failed"
	PaymentStatusRefunded  PaymentStatus = "refunded"
	PaymentStatusCanceled  PaymentStatus = "canceled"
)

type PaymentSucceededEvent

type PaymentSucceededEvent struct {
	EventID           string    `json:"event_id"`
	EventType         string    `json:"event_type"`
	OccurredAt        time.Time `json:"occurred_at"`
	PaymentID         string    `json:"payment_id"`
	OrganizationID    string    `json:"organization_id"`
	InvoiceID         string    `json:"invoice_id"`
	Amount            string    `json:"amount"`
	Currency          string    `json:"currency"`
	PaymentMethod     string    `json:"payment_method"`
	ProviderPaymentID string    `json:"provider_payment_id"`
	SucceededAt       time.Time `json:"succeeded_at"`
}

PaymentSucceededEvent represents a successful payment event

type PricingEngine

type PricingEngine struct {
	// contains filtered or unexported fields
}

PricingEngine handles all pricing calculations

func NewPricingEngine

func NewPricingEngine(config *Config) *PricingEngine

NewPricingEngine creates a new pricing engine

func (*PricingEngine) CalculateProration

func (pe *PricingEngine) CalculateProration(
	oldPrice, newPrice decimal.Decimal,
	periodStart, periodEnd, changeDate time.Time,
) decimal.Decimal

CalculateProration calculates prorated charges for mid-cycle changes

func (*PricingEngine) CalculateSubscriptionCharge

func (pe *PricingEngine) CalculateSubscriptionCharge(
	subscription *models.Subscription,
	plan *models.SubscriptionPlan,
	usage *UsageAggregation,
	credits []models.Credit,
) (*ChargeCalculation, error)

CalculateSubscriptionCharge calculates the charge for a subscription period

func (*PricingEngine) CalculateTieredPrice

func (pe *PricingEngine) CalculateTieredPrice(
	usage decimal.Decimal,
	tiers []models.PricingTier,
) decimal.Decimal

CalculateTieredPrice calculates price using volume-based tiers

func (*PricingEngine) EstimateMonthlyCharge

func (pe *PricingEngine) EstimateMonthlyCharge(
	plan *models.SubscriptionPlan,
	quantity int,
	estimatedUsage map[MetricType]decimal.Decimal,
) decimal.Decimal

EstimateMonthlyCharge estimates the monthly charge for a subscription

type PricingTier

type PricingTier struct {
	TierStart    decimal.Decimal  // Inclusive lower bound
	TierEnd      *decimal.Decimal // Exclusive upper bound (nil = infinity)
	PricePerUnit decimal.Decimal
	FlatFee      decimal.Decimal
}

PricingTier represents a volume-based pricing tier

type RateLimitConfig

type RateLimitConfig struct {
	RequestsPerSecond int // Maximum requests per second
	BurstSize         int // Maximum burst size
}

RateLimitConfig contains API rate limiting settings

type StripeConfig

type StripeConfig struct {
	APIKey        string
	WebhookSecret string
	Enabled       bool
}

StripeConfig contains Stripe payment provider settings

type SubscriptionCanceledEvent

type SubscriptionCanceledEvent struct {
	EventID            string    `json:"event_id"`
	EventType          string    `json:"event_type"`
	OccurredAt         time.Time `json:"occurred_at"`
	SubscriptionID     string    `json:"subscription_id"`
	OrganizationID     string    `json:"organization_id"`
	CancellationReason string    `json:"cancellation_reason"`
	CanceledAt         time.Time `json:"canceled_at"`
	EndDate            time.Time `json:"end_date"`
}

SubscriptionCanceledEvent represents a subscription cancellation event

type SubscriptionChange

type SubscriptionChange struct {
	SubscriptionID string
	FromPlanID     string
	ToPlanID       string
	ChangeType     string // upgrade, downgrade
	Proration      decimal.Decimal
	EffectiveDate  time.Time
}

SubscriptionChange represents a change to a subscription (upgrade/downgrade)

type SubscriptionCreatedEvent

type SubscriptionCreatedEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	SubscriptionID string    `json:"subscription_id"`
	OrganizationID string    `json:"organization_id"`
	PlanID         string    `json:"plan_id"`
	PlanName       string    `json:"plan_name"`
	Status         string    `json:"status"`
	PeriodStart    time.Time `json:"period_start"`
	PeriodEnd      time.Time `json:"period_end"`
	Amount         string    `json:"amount"`
	Currency       string    `json:"currency"`
}

SubscriptionCreatedEvent represents a subscription creation event

type SubscriptionStatus

type SubscriptionStatus string

SubscriptionStatus represents the current state of a subscription

const (
	SubscriptionStatusActive     SubscriptionStatus = "active"
	SubscriptionStatusCanceled   SubscriptionStatus = "canceled"
	SubscriptionStatusPastDue    SubscriptionStatus = "past_due"
	SubscriptionStatusTrialing   SubscriptionStatus = "trialing"
	SubscriptionStatusIncomplete SubscriptionStatus = "incomplete"
)

type SubscriptionUpdatedEvent

type SubscriptionUpdatedEvent struct {
	EventID        string                 `json:"event_id"`
	EventType      string                 `json:"event_type"`
	OccurredAt     time.Time              `json:"occurred_at"`
	SubscriptionID string                 `json:"subscription_id"`
	OrganizationID string                 `json:"organization_id"`
	Changes        map[string]interface{} `json:"changes"`
}

SubscriptionUpdatedEvent represents a subscription update event

type UsageAggregation

type UsageAggregation struct {
	OrganizationID string
	SubscriptionID string
	PeriodStart    time.Time
	PeriodEnd      time.Time
	Metrics        map[MetricType]decimal.Decimal
}

UsageAggregation represents aggregated usage for a billing period

type UsageConfig

type UsageConfig struct {
	AggregationInterval time.Duration // How often to aggregate usage metrics
	RetentionDays       int           // How long to retain detailed usage data
	BatchSize           int           // Batch size for metric processing
	EnableRealTime      bool          // Enable real-time usage tracking
}

UsageConfig contains usage metrics collection settings

type UsageRecord

type UsageRecord struct {
	OrganizationID string
	SubscriptionID string
	MetricType     MetricType
	MetricValue    decimal.Decimal
	MetricUnit     string
	RecordedAt     time.Time
	PeriodStart    time.Time
	PeriodEnd      time.Time
	ResourceID     string
	Metadata       map[string]interface{}
}

UsageRecord represents a single usage metric record

type UsageThresholdReachedEvent

type UsageThresholdReachedEvent struct {
	EventID        string    `json:"event_id"`
	EventType      string    `json:"event_type"`
	OccurredAt     time.Time `json:"occurred_at"`
	OrganizationID string    `json:"organization_id"`
	MetricType     string    `json:"metric_type"`
	CurrentUsage   string    `json:"current_usage"`
	Threshold      string    `json:"threshold"`
	PercentUsed    int       `json:"percent_used"`
}

UsageThresholdReachedEvent represents a usage threshold event

type WebhookEvent

type WebhookEvent struct {
	Provider   PaymentProvider
	EventType  string
	EventID    string
	Payload    map[string]interface{}
	Signature  string
	ReceivedAt time.Time
}

WebhookEvent represents a payment provider webhook event

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL