Documentation
¶
Overview ¶
Package core defines the core domain types for the subscription plugin.
Package core defines the core domain types for the subscription plugin. These types have no external dependencies and define the business domain model.
Index ¶
- Constants
- Variables
- func CalculateARPU(totalMRR int64, totalCustomers int) int64
- func CalculateARR(mrr int64) int64
- func CalculateChurnRate(customersChurned, customersAtStart int) float64
- func CalculateLTV(arpu int64, churnRate float64) int64
- func CalculateMRR(subscription *Subscription, plan *Plan) int64
- func CalculateNetRevenueRetention(mrrAtStart, newMRR, expansionMRR, contractionMRR, churnedMRR int64) float64
- func FormatAmount(amount int64, currency string) string
- type AcknowledgeAlertRequest
- type AddOn
- type AddPaymentMethodRequest
- type Alert
- type AlertChannel
- type AlertConfig
- type AlertSeverity
- type AlertStatus
- type AlertSummary
- type AlertTemplate
- type AlertType
- type AppliedDiscount
- type AttachAddOnRequest
- type BillingAddress
- type BillingInterval
- type BillingMetric
- type BillingPattern
- type CalculateTaxRequest
- type CancelSubscriptionRequest
- type ChurnAnalysis
- type CohortAnalysis
- type CohortAnalysisResponse
- type Config
- type ConsumeFeatureRequest
- type ConvertCurrencyRequest
- type ConvertCurrencyResponse
- type Coupon
- type CouponDuration
- type CouponError
- type CouponRedemption
- type CouponStatus
- type CouponType
- type CreateAddOnRequest
- type CreateAlertConfigRequest
- type CreateCouponRequest
- type CreateCustomerRequest
- type CreateExchangeRateRequest
- type CreateFeatureRequest
- type CreatePlanRequest
- type CreatePromotionCodeRequest
- type CreateSubscriptionRequest
- type CreateTaxExemptionRequest
- type CreateTaxIDRequest
- type CreateTaxRateRequest
- type CurrencyAmount
- type Customer
- type CustomerTaxID
- type DashboardMetrics
- type EventType
- type ExchangeRate
- type ExportMetricsRequest
- type Feature
- type FeatureAccess
- type FeatureGrant
- type FeatureGrantType
- type FeatureTier
- type FeatureType
- type FeatureUsageAction
- type FeatureUsageLog
- type FeatureUsageResponse
- type GetCohortAnalysisRequest
- type GetMetricsRequest
- type GetUsageSummaryRequest
- type GrantFeatureRequest
- type Invoice
- func (i *Invoice) AddItem(description string, quantity, unitAmount int64) *InvoiceItem
- func (i *Invoice) Finalize()
- func (i *Invoice) IsDraft() bool
- func (i *Invoice) IsOpen() bool
- func (i *Invoice) IsOverdue() bool
- func (i *Invoice) IsPaid() bool
- func (i *Invoice) MarkPaid()
- func (i *Invoice) Void()
- type InvoiceItem
- type InvoiceMetrics
- type InvoiceStatus
- type LinkFeatureRequest
- type ListInvoicesFilter
- type ListUsageRecordsFilter
- type MRRBreakdown
- type MetricPeriod
- type MetricType
- type MetricsResponse
- type MultiCurrencyPrice
- type OrganizationFeatureUsage
- type PauseSubscriptionRequest
- type PaymentMethod
- type PaymentMethodType
- type Plan
- func (p *Plan) AddPriceTier(upTo, unitAmount, flatAmount int64)
- func (p *Plan) CalculateTieredPrice(quantity int64) int64
- func (p *Plan) GetFeature(key string) *PlanFeature
- func (p *Plan) GetFeatureLimit(key string) int64
- func (p *Plan) HasFeature(key string) bool
- func (p *Plan) SetFeature(key, name string, featureType FeatureType, value any)
- type PlanFeature
- type PlanFeatureLink
- type PriceTier
- type PromotionCode
- type PublicFeature
- type PublicPlanFeature
- type RecordUsageRequest
- type RedeemCouponRequest
- type ResetPeriod
- type ResolveAlertRequest
- type RevenueByPlan
- type RevenueBySegment
- type SetupIntentResult
- type SnoozeAlertRequest
- type StripeConfig
- type Subscription
- func (s *Subscription) ActivateFromTrial()
- func (s *Subscription) Cancel(immediate bool)
- func (s *Subscription) DaysUntilRenewal() int
- func (s *Subscription) DaysUntilTrialEnd() int
- func (s *Subscription) IsActive() bool
- func (s *Subscription) IsCanceled() bool
- func (s *Subscription) IsPastDue() bool
- func (s *Subscription) IsPaused() bool
- func (s *Subscription) IsTrialing() bool
- func (s *Subscription) Pause(resumeAt *time.Time)
- func (s *Subscription) Resume()
- func (s *Subscription) StartTrial(days int)
- func (s *Subscription) WillCancel() bool
- type SubscriptionAddOn
- type SubscriptionMovement
- type SubscriptionStatus
- type SupportedCurrency
- type TaxBehavior
- type TaxBillingAddress
- type TaxCalculation
- type TaxExemption
- type TaxIDType
- type TaxRate
- type TaxSummary
- type TaxType
- type TierMode
- type TrialMetrics
- type TriggerAlertRequest
- type UpdateAddOnRequest
- type UpdateAlertConfigRequest
- type UpdateCouponRequest
- type UpdateCustomerRequest
- type UpdateExchangeRateRequest
- type UpdateFeatureRequest
- type UpdateLinkRequest
- type UpdatePlanRequest
- type UpdateSubscriptionRequest
- type UpdateTaxRateRequest
- type UsageAction
- type UsageLimit
- type UsageMetric
- type UsageRecord
- type UsageSnapshot
- type UsageSummary
- type VATValidationResult
- type ValidateCouponRequest
- type ValidateCouponResponse
Constants ¶
const ( CurrencyUSD = "USD" CurrencyEUR = "EUR" CurrencyGBP = "GBP" CurrencyJPY = "JPY" CurrencyCAD = "CAD" CurrencyAUD = "AUD" CurrencyCHF = "CHF" CurrencyCNY = "CNY" CurrencyINR = "INR" CurrencyBRL = "BRL" )
Common currency codes
const ( FeatureKeyMaxMembers = "max_members" FeatureKeyMaxTeams = "max_teams" FeatureKeyMaxProjects = "max_projects" FeatureKeyMaxStorage = "max_storage_gb" FeatureKeyMaxAPICallsMonth = "max_api_calls_month" FeatureKeyCustomDomain = "custom_domain" FeatureKeyPrioritySupport = "priority_support" FeatureKeySSO = "sso" FeatureKeyAuditLogs = "audit_logs" FeatureKeyAdvancedAnalytics = "advanced_analytics" )
Feature keys for common plan features
const ( UsageMetricAPICalls = "api_calls" UsageMetricStorageGB = "storage_gb" UsageMetricBandwidthGB = "bandwidth_gb" UsageMetricActiveUsers = "active_users" UsageMetricMessages = "messages" UsageMetricCompute = "compute_hours" )
Common usage metric keys
const DefaultCurrency = "USD"
DefaultCurrency is the default currency if not specified
Variables ¶
var ( ErrCouponNotFound = &CouponError{Code: "COUPON_NOT_FOUND", Message: "coupon not found"} ErrCouponExpired = &CouponError{Code: "COUPON_EXPIRED", Message: "coupon has expired"} ErrCouponNotYetValid = &CouponError{Code: "COUPON_NOT_YET_VALID", Message: "coupon is not yet valid"} ErrCouponMaxRedemptions = &CouponError{Code: "COUPON_MAX_REDEMPTIONS", Message: "coupon has reached maximum redemptions"} ErrCouponNotApplicable = &CouponError{Code: "COUPON_NOT_APPLICABLE", Message: "coupon is not applicable to this plan"} ErrCouponMinPurchase = &CouponError{Code: "COUPON_MIN_PURCHASE", Message: "purchase amount does not meet minimum"} ErrCouponAlreadyUsed = &CouponError{Code: "COUPON_ALREADY_USED", Message: "coupon has already been used by this organization"} ErrCouponFirstPurchase = &CouponError{Code: "COUPON_FIRST_PURCHASE", Message: "coupon is only valid for first purchase"} ErrCouponCodeExists = &CouponError{Code: "COUPON_CODE_EXISTS", Message: "coupon code already exists"} )
Common coupon errors
Functions ¶
func CalculateARPU ¶
CalculateARPU calculates Average Revenue Per User
func CalculateChurnRate ¶
CalculateChurnRate calculates the churn rate
func CalculateLTV ¶
CalculateLTV calculates Customer Lifetime Value
func CalculateMRR ¶
func CalculateMRR(subscription *Subscription, plan *Plan) int64
CalculateMRR calculates MRR from a subscription
func CalculateNetRevenueRetention ¶
func CalculateNetRevenueRetention(mrrAtStart, newMRR, expansionMRR, contractionMRR, churnedMRR int64) float64
CalculateNetRevenueRetention calculates NRR
func FormatAmount ¶
FormatAmount formats an amount for display
Types ¶
type AcknowledgeAlertRequest ¶
type AcknowledgeAlertRequest struct {
AlertID xid.ID `json:"alertId" validate:"required"`
AcknowledgedBy string `json:"acknowledgedBy"`
}
AcknowledgeAlertRequest is used to acknowledge an alert
type AddOn ¶
type AddOn struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"` // Scoped to app
Name string `json:"name"` // Display name
Slug string `json:"slug"` // URL-safe identifier
Description string `json:"description"` // Marketing description
BillingPattern BillingPattern `json:"billingPattern"` // How the add-on is billed
BillingInterval BillingInterval `json:"billingInterval"` // Billing frequency
Price int64 `json:"price"` // Price in cents
Currency string `json:"currency"` // ISO 4217 currency code
Features []PlanFeature `json:"features"` // Features provided by this add-on
PriceTiers []PriceTier `json:"priceTiers"` // For usage-based add-ons
TierMode TierMode `json:"tierMode"` // How tiers are applied
Metadata map[string]any `json:"metadata"` // Custom metadata
IsActive bool `json:"isActive"` // Available for purchase
IsPublic bool `json:"isPublic"` // Visible in public listing
DisplayOrder int `json:"displayOrder"` // Display order
ProviderPriceID string `json:"providerPriceId"` // Stripe Price ID
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// Constraints
RequiresPlanIDs []xid.ID `json:"requiresPlanIds"` // Only available with these plans
ExcludesPlanIDs []xid.ID `json:"excludesPlanIds"` // Not available with these plans
MaxQuantity int `json:"maxQuantity"` // Maximum quantity per subscription (0 = unlimited)
}
AddOn represents an optional add-on that can be attached to subscriptions
func (*AddOn) CalculatePrice ¶
CalculatePrice calculates the price for a given quantity
func (*AddOn) GetFeature ¶
func (a *AddOn) GetFeature(key string) *PlanFeature
GetFeature returns a feature by key, or nil if not found
type AddPaymentMethodRequest ¶
type AddPaymentMethodRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
Type PaymentMethodType `json:"type" validate:"required"`
SetAsDefault bool `json:"setAsDefault"`
BillingName string `json:"billingName"`
BillingEmail string `json:"billingEmail" validate:"omitempty,email"`
BillingPhone string `json:"billingPhone"`
BillingAddress *BillingAddress `json:"billingAddress"`
}
AddPaymentMethodRequest represents a request to add a payment method
type Alert ¶
type Alert struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
OrganizationID xid.ID `json:"organizationId"`
ConfigID *xid.ID `json:"configId"` // Reference to AlertConfig
// Alert details
Type AlertType `json:"type"`
Severity AlertSeverity `json:"severity"`
Status AlertStatus `json:"status"`
Title string `json:"title"`
Message string `json:"message"`
// Context data
MetricKey string `json:"metricKey"`
CurrentValue float64 `json:"currentValue"`
ThresholdValue float64 `json:"thresholdValue"`
LimitValue float64 `json:"limitValue"`
// Related entities
SubscriptionID *xid.ID `json:"subscriptionId"`
InvoiceID *xid.ID `json:"invoiceId"`
// Delivery tracking
Channels []AlertChannel `json:"channels"`
SentAt *time.Time `json:"sentAt"`
DeliveryStatus map[string]string `json:"deliveryStatus"` // Channel -> status
// Acknowledgment
AcknowledgedAt *time.Time `json:"acknowledgedAt"`
AcknowledgedBy string `json:"acknowledgedBy"`
// Resolution
ResolvedAt *time.Time `json:"resolvedAt"`
Resolution string `json:"resolution"`
// Metadata
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Alert represents an individual alert instance
type AlertChannel ¶
type AlertChannel string
AlertChannel represents how an alert is delivered
const ( AlertChannelEmail AlertChannel = "email" AlertChannelWebhook AlertChannel = "webhook" AlertChannelInApp AlertChannel = "in_app" AlertChannelSMS AlertChannel = "sms" AlertChannelSlack AlertChannel = "slack" )
type AlertConfig ¶
type AlertConfig struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
OrganizationID xid.ID `json:"organizationId"`
// Alert type settings
AlertType AlertType `json:"alertType"`
IsEnabled bool `json:"isEnabled"`
// Threshold settings (for usage alerts)
ThresholdPercent float64 `json:"thresholdPercent"` // Trigger at X% (e.g., 80, 90, 100)
MetricKey string `json:"metricKey"` // Which metric to monitor
// Timing settings
DaysBeforeEnd int `json:"daysBeforeEnd"` // For trial/subscription ending alerts
// Delivery settings
Channels []AlertChannel `json:"channels"`
Recipients []string `json:"recipients"` // Email addresses
WebhookURL string `json:"webhookUrl"` // For webhook channel
SlackChannel string `json:"slackChannel"` // For Slack channel
// Frequency settings
MinInterval int `json:"minInterval"` // Minimum minutes between alerts
MaxAlertsPerDay int `json:"maxAlertsPerDay"` // Max alerts per day (0 = unlimited)
// Snooze settings
SnoozedUntil *time.Time `json:"snoozedUntil"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
AlertConfig represents alert configuration for an organization
func DefaultAlertConfigs ¶
func DefaultAlertConfigs(appID, orgID xid.ID) []AlertConfig
DefaultAlertConfigs returns default alert configurations for a new organization
type AlertSeverity ¶
type AlertSeverity string
AlertSeverity represents the severity level of an alert
const ( AlertSeverityInfo AlertSeverity = "info" AlertSeverityWarning AlertSeverity = "warning" AlertSeverityCritical AlertSeverity = "critical" )
type AlertStatus ¶
type AlertStatus string
AlertStatus represents the status of an alert
const ( AlertStatusPending AlertStatus = "pending" // Alert created, not yet sent AlertStatusSent AlertStatus = "sent" // Alert sent AlertStatusAcknowledged AlertStatus = "acknowledged" // Alert acknowledged by user AlertStatusResolved AlertStatus = "resolved" // Alert condition resolved AlertStatusSnoozed AlertStatus = "snoozed" // Alert snoozed )
type AlertSummary ¶
type AlertSummary struct {
TotalAlerts int `json:"totalAlerts"`
PendingAlerts int `json:"pendingAlerts"`
SentAlerts int `json:"sentAlerts"`
AcknowledgedAlerts int `json:"acknowledgedAlerts"`
BySeverity map[AlertSeverity]int `json:"bySeverity"`
ByType map[AlertType]int `json:"byType"`
RecentAlerts []Alert `json:"recentAlerts"`
}
AlertSummary provides a summary of alerts for an organization
type AlertTemplate ¶
type AlertTemplate struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
AlertType AlertType `json:"alertType"`
Channel AlertChannel `json:"channel"`
// Template content
Subject string `json:"subject"` // For email
TitleTemplate string `json:"titleTemplate"`
BodyTemplate string `json:"bodyTemplate"`
IsDefault bool `json:"isDefault"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
AlertTemplate represents an alert message template
func DefaultAlertTemplates ¶
func DefaultAlertTemplates(appID xid.ID) []AlertTemplate
DefaultAlertTemplates returns default alert templates
type AlertType ¶
type AlertType string
AlertType represents the type of usage alert
const ( AlertTypeUsageThreshold AlertType = "usage_threshold" // When usage reaches X% AlertTypeUsageLimit AlertType = "usage_limit" // When usage hits limit AlertTypePaymentFailed AlertType = "payment_failed" // Payment failure AlertTypeTrialEnding AlertType = "trial_ending" // Trial about to end AlertTypeSubscriptionExpiring AlertType = "subscription_expiring" // Subscription expiring AlertTypeInvoicePastDue AlertType = "invoice_past_due" // Invoice past due AlertTypeSeatLimitApproaching AlertType = "seat_limit_approaching" // Seat limit approaching )
type AppliedDiscount ¶
type AppliedDiscount struct {
CouponID xid.ID `json:"couponId"`
CouponCode string `json:"couponCode"`
Type CouponType `json:"type"`
OriginalAmount int64 `json:"originalAmount"`
DiscountAmount int64 `json:"discountAmount"`
FinalAmount int64 `json:"finalAmount"`
Description string `json:"description"`
}
AppliedDiscount represents a discount applied to an invoice line item
type AttachAddOnRequest ¶
type AttachAddOnRequest struct {
SubscriptionID xid.ID `json:"subscriptionId" validate:"required"`
AddOnID xid.ID `json:"addOnId" validate:"required"`
Quantity int `json:"quantity" validate:"min=1"`
}
AttachAddOnRequest represents a request to attach an add-on to a subscription
type BillingAddress ¶
type BillingAddress struct {
Line1 string `json:"line1"`
Line2 string `json:"line2"`
City string `json:"city"`
State string `json:"state"`
PostalCode string `json:"postalCode"`
Country string `json:"country" validate:"len=2"` // ISO 3166-1 alpha-2
}
BillingAddress represents a billing address
type BillingInterval ¶
type BillingInterval string
BillingInterval defines the billing frequency
const ( // BillingIntervalMonthly bills every month BillingIntervalMonthly BillingInterval = "monthly" // BillingIntervalYearly bills every year BillingIntervalYearly BillingInterval = "yearly" // BillingIntervalOneTime is a one-time charge BillingIntervalOneTime BillingInterval = "one_time" )
func (BillingInterval) IsValid ¶
func (b BillingInterval) IsValid() bool
IsValid checks if the billing interval is valid
func (BillingInterval) String ¶
func (b BillingInterval) String() string
String returns the string representation of the billing interval
type BillingMetric ¶
type BillingMetric struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
Type MetricType `json:"type"`
Period MetricPeriod `json:"period"`
Value float64 `json:"value"`
Currency string `json:"currency"`
Date time.Time `json:"date"` // The date this metric is for
CreatedAt time.Time `json:"createdAt"`
}
BillingMetric represents a point-in-time billing metric
type BillingPattern ¶
type BillingPattern string
BillingPattern defines how a plan or add-on is billed
const ( // BillingPatternFlat is a fixed price per billing period BillingPatternFlat BillingPattern = "flat" // BillingPatternPerSeat charges per user/member BillingPatternPerSeat BillingPattern = "per_seat" // BillingPatternTiered uses volume-based pricing tiers BillingPatternTiered BillingPattern = "tiered" // BillingPatternUsage is pay-per-use metered billing BillingPatternUsage BillingPattern = "usage" // BillingPatternHybrid combines base price with usage BillingPatternHybrid BillingPattern = "hybrid" )
func (BillingPattern) IsValid ¶
func (b BillingPattern) IsValid() bool
IsValid checks if the billing pattern is valid
func (BillingPattern) String ¶
func (b BillingPattern) String() string
String returns the string representation of the billing pattern
type CalculateTaxRequest ¶
type CalculateTaxRequest struct {
Amount int64 `json:"amount" validate:"required"`
Currency string `json:"currency" validate:"required,len=3"`
BillingAddress *BillingAddress `json:"billingAddress"`
OrganizationID *xid.ID `json:"organizationId"`
ProductType string `json:"productType"` // For product-specific tax rules
}
CalculateTaxRequest is used to calculate tax for an amount
type CancelSubscriptionRequest ¶
type CancelSubscriptionRequest struct {
Immediate bool `json:"immediate"` // If true, cancel immediately; otherwise at period end
Reason string `json:"reason"` // Cancellation reason
}
CancelSubscriptionRequest represents a request to cancel a subscription
type ChurnAnalysis ¶
type ChurnAnalysis struct {
Period MetricPeriod `json:"period"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
// Customer churn
CustomersAtStart int `json:"customersAtStart"`
CustomersAtEnd int `json:"customersAtEnd"`
CustomersChurned int `json:"customersChurned"`
CustomerChurnRate float64 `json:"customerChurnRate"` // Percentage
// Revenue churn
MRRAtStart int64 `json:"mrrAtStart"`
MRRAtEnd int64 `json:"mrrAtEnd"`
MRRChurned int64 `json:"mrrChurned"`
RevenueChurnRate float64 `json:"revenueChurnRate"` // Percentage
NetRevenueRetention float64 `json:"netRevenueRetention"` // Percentage (can be >100%)
// Breakdown by reason
ChurnByReason map[string]int `json:"churnByReason"` // Reason -> count
ChurnByPlan map[string]int `json:"churnByPlan"` // Plan slug -> count
Currency string `json:"currency"`
}
ChurnAnalysis provides detailed churn analysis
type CohortAnalysis ¶
type CohortAnalysis struct {
CohortMonth time.Time `json:"cohortMonth"` // The month customers signed up
TotalCustomers int `json:"totalCustomers"`
Retention []float64 `json:"retention"` // Retention rate for each subsequent month
Revenue []int64 `json:"revenue"` // Revenue for each subsequent month
Currency string `json:"currency"`
}
CohortAnalysis represents a cohort analysis for retention
type CohortAnalysisResponse ¶
type CohortAnalysisResponse struct {
Cohorts []CohortAnalysis `json:"cohorts"`
Currency string `json:"currency"`
}
CohortAnalysisResponse contains cohort analysis results
type Config ¶
type Config struct {
// General settings
Enabled bool `json:"enabled"`
RequireSubscription bool `json:"requireSubscription"` // Require subscription to create org
// Trial settings
DefaultTrialDays int `json:"defaultTrialDays"`
TrialAllowedPlans []string `json:"trialAllowedPlans"` // Plan slugs that allow trials
// Grace period
GracePeriodDays int `json:"gracePeriodDays"` // Days before suspending on failed payment
// Seat management
AutoSyncSeats bool `json:"autoSyncSeats"` // Auto-update quantity based on org members
// Plan sync settings
AutoSyncPlans bool `json:"autoSyncPlans"` // Auto-sync plans to payment provider on create/update
// Provider configuration
Provider string `json:"provider"` // stripe, paddle, etc.
StripeConfig StripeConfig `json:"stripe"`
// Webhook settings
WebhookTolerance int `json:"webhookTolerance"` // Seconds tolerance for webhook timestamp
// Metering settings
UsageReportBatchSize int `json:"usageReportBatchSize"` // Batch size for usage reporting
UsageReportInterval int `json:"usageReportInterval"` // Seconds between usage reports
}
Config holds the subscription plugin configuration
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the default plugin configuration
func (*Config) GetWebhookSecret ¶
GetWebhookSecret returns the appropriate webhook secret based on provider
func (*Config) IsStripeConfigured ¶
IsStripeConfigured returns true if Stripe is properly configured
type ConsumeFeatureRequest ¶
type ConsumeFeatureRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
FeatureKey string `json:"featureKey" validate:"required"`
Quantity int64 `json:"quantity" validate:"required,min=1"`
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Reason string `json:"reason,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
ConsumeFeatureRequest represents a request to consume feature quota
type ConvertCurrencyRequest ¶
type ConvertCurrencyRequest struct {
Amount int64 `json:"amount" validate:"required"`
FromCurrency string `json:"fromCurrency" validate:"required,len=3"`
ToCurrency string `json:"toCurrency" validate:"required,len=3"`
}
ConvertCurrencyRequest is used to convert between currencies
type ConvertCurrencyResponse ¶
type ConvertCurrencyResponse struct {
OriginalAmount int64 `json:"originalAmount"`
OriginalCurrency string `json:"originalCurrency"`
ConvertedAmount int64 `json:"convertedAmount"`
ConvertedCurrency string `json:"convertedCurrency"`
ExchangeRate float64 `json:"exchangeRate"`
ConvertedAt time.Time `json:"convertedAt"`
}
ConvertCurrencyResponse contains the conversion result
type Coupon ¶
type Coupon struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
Code string `json:"code"` // Unique coupon code (e.g., "SUMMER2024")
Name string `json:"name"` // Display name
Description string `json:"description"` // Optional description
Type CouponType `json:"type"` // Type of discount
Duration CouponDuration `json:"duration"` // How long it applies
Status CouponStatus `json:"status"`
// Discount values (depending on type)
PercentOff float64 `json:"percentOff"` // Percentage off (0-100)
AmountOff int64 `json:"amountOff"` // Fixed amount off (in smallest currency unit)
Currency string `json:"currency"` // Currency for fixed amount
TrialDays int `json:"trialDays"` // Additional trial days
FreeMonths int `json:"freeMonths"` // Number of free months
// Duration settings
DurationMonths int `json:"durationMonths"` // For repeating duration
// Restrictions
MaxRedemptions int `json:"maxRedemptions"` // Max total redemptions (0 = unlimited)
MaxRedemptionsPerOrg int `json:"maxRedemptionsPerOrg"` // Max per organization
MinPurchaseAmount int64 `json:"minPurchaseAmount"` // Minimum purchase amount
ApplicablePlans []string `json:"applicablePlans"` // Plan slugs this applies to (empty = all)
ApplicableAddOns []string `json:"applicableAddOns"` // Add-on slugs this applies to
FirstPurchaseOnly bool `json:"firstPurchaseOnly"` // Only for first purchase
// Validity
ValidFrom time.Time `json:"validFrom"`
ValidUntil *time.Time `json:"validUntil"`
// Usage tracking
TimesRedeemed int `json:"timesRedeemed"` // Number of times redeemed
// Provider integration
ProviderCouponID string `json:"providerCouponId"` // Coupon ID in payment provider
// Metadata
Metadata map[string]interface{} `json:"metadata"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Coupon represents a discount coupon
func (*Coupon) CalculateDiscount ¶
CalculateDiscount calculates the discount amount for a given price
type CouponDuration ¶
type CouponDuration string
CouponDuration defines how long a coupon applies
const ( CouponDurationOnce CouponDuration = "once" // Apply once CouponDurationRepeating CouponDuration = "repeating" // Apply for X months CouponDurationForever CouponDuration = "forever" // Apply forever )
type CouponError ¶
CouponError represents a coupon-related error
func (*CouponError) Error ¶
func (e *CouponError) Error() string
type CouponRedemption ¶
type CouponRedemption struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
CouponID xid.ID `json:"couponId"`
OrganizationID xid.ID `json:"organizationId"`
SubscriptionID xid.ID `json:"subscriptionId"`
// Applied discount
DiscountType CouponType `json:"discountType"`
DiscountAmount int64 `json:"discountAmount"` // Actual amount discounted
Currency string `json:"currency"`
RedeemedAt time.Time `json:"redeemedAt"`
ExpiresAt *time.Time `json:"expiresAt"` // When the discount stops applying
}
CouponRedemption tracks when a coupon is used
type CouponStatus ¶
type CouponStatus string
CouponStatus represents the status of a coupon
const ( CouponStatusActive CouponStatus = "active" CouponStatusExpired CouponStatus = "expired" CouponStatusArchived CouponStatus = "archived" )
type CouponType ¶
type CouponType string
CouponType represents the type of discount a coupon provides
const ( CouponTypePercentage CouponType = "percentage" // Percentage off (e.g., 20% off) CouponTypeFixedAmount CouponType = "fixed_amount" // Fixed amount off (e.g., $10 off) CouponTypeTrialExtension CouponType = "trial_extension" // Extend trial period CouponTypeFreeMonths CouponType = "free_months" // Free months )
type CreateAddOnRequest ¶
type CreateAddOnRequest struct {
Name string `json:"name" validate:"required,min=1,max=100"`
Slug string `json:"slug" validate:"required,min=1,max=50,alphanum"`
Description string `json:"description" validate:"max=1000"`
BillingPattern BillingPattern `json:"billingPattern" validate:"required"`
BillingInterval BillingInterval `json:"billingInterval" validate:"required"`
Price int64 `json:"price" validate:"min=0"`
Currency string `json:"currency" validate:"len=3"`
Features []PlanFeature `json:"features"`
PriceTiers []PriceTier `json:"priceTiers"`
TierMode TierMode `json:"tierMode"`
Metadata map[string]any `json:"metadata"`
IsActive bool `json:"isActive"`
IsPublic bool `json:"isPublic"`
DisplayOrder int `json:"displayOrder"`
RequiresPlanIDs []xid.ID `json:"requiresPlanIds"`
ExcludesPlanIDs []xid.ID `json:"excludesPlanIds"`
MaxQuantity int `json:"maxQuantity"`
}
CreateAddOnRequest represents a request to create an add-on
type CreateAlertConfigRequest ¶
type CreateAlertConfigRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
AlertType AlertType `json:"alertType" validate:"required"`
ThresholdPercent float64 `json:"thresholdPercent"`
MetricKey string `json:"metricKey"`
DaysBeforeEnd int `json:"daysBeforeEnd"`
Channels []AlertChannel `json:"channels" validate:"required,min=1"`
Recipients []string `json:"recipients"`
WebhookURL string `json:"webhookUrl"`
SlackChannel string `json:"slackChannel"`
MinInterval int `json:"minInterval"`
MaxAlertsPerDay int `json:"maxAlertsPerDay"`
}
CreateAlertConfigRequest is used to create an alert configuration
type CreateCouponRequest ¶
type CreateCouponRequest struct {
Code string `json:"code" validate:"required,min=3,max=50"`
Name string `json:"name" validate:"required"`
Description string `json:"description"`
Type CouponType `json:"type" validate:"required"`
Duration CouponDuration `json:"duration" validate:"required"`
PercentOff float64 `json:"percentOff"`
AmountOff int64 `json:"amountOff"`
Currency string `json:"currency"`
TrialDays int `json:"trialDays"`
FreeMonths int `json:"freeMonths"`
DurationMonths int `json:"durationMonths"`
MaxRedemptions int `json:"maxRedemptions"`
MaxRedemptionsPerOrg int `json:"maxRedemptionsPerOrg"`
MinPurchaseAmount int64 `json:"minPurchaseAmount"`
ApplicablePlans []string `json:"applicablePlans"`
ApplicableAddOns []string `json:"applicableAddOns"`
FirstPurchaseOnly bool `json:"firstPurchaseOnly"`
ValidFrom time.Time `json:"validFrom"`
ValidUntil *time.Time `json:"validUntil"`
Metadata map[string]interface{} `json:"metadata"`
}
CreateCouponRequest is used to create a new coupon
type CreateCustomerRequest ¶
type CreateCustomerRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
Email string `json:"email" validate:"required,email"`
Name string `json:"name" validate:"required"`
Phone string `json:"phone"`
TaxID string `json:"taxId"`
TaxExempt bool `json:"taxExempt"`
BillingAddress *BillingAddress `json:"billingAddress"`
Metadata map[string]any `json:"metadata"`
}
CreateCustomerRequest represents a request to create a customer
type CreateExchangeRateRequest ¶
type CreateExchangeRateRequest struct {
FromCurrency string `json:"fromCurrency" validate:"required,len=3"`
ToCurrency string `json:"toCurrency" validate:"required,len=3"`
Rate float64 `json:"rate" validate:"required,gt=0"`
ValidFrom time.Time `json:"validFrom"`
Source string `json:"source"`
}
CreateExchangeRateRequest is used to create a new exchange rate
type CreateFeatureRequest ¶
type CreateFeatureRequest struct {
Key string `json:"key" validate:"required,min=1,max=100"`
Name string `json:"name" validate:"required,min=1,max=100"`
Description string `json:"description" validate:"max=1000"`
Type FeatureType `json:"type" validate:"required"`
Unit string `json:"unit" validate:"max=50"`
ResetPeriod ResetPeriod `json:"resetPeriod"`
IsPublic bool `json:"isPublic"`
DisplayOrder int `json:"displayOrder"`
Icon string `json:"icon" validate:"max=100"`
Metadata map[string]any `json:"metadata,omitempty"`
Tiers []FeatureTier `json:"tiers,omitempty"` // For tiered features
}
CreateFeatureRequest represents a request to create a new feature
type CreatePlanRequest ¶
type CreatePlanRequest struct {
Name string `json:"name" validate:"required,min=1,max=100"`
Slug string `json:"slug" validate:"required,min=1,max=50,alphanum"`
Description string `json:"description" validate:"max=1000"`
BillingPattern BillingPattern `json:"billingPattern" validate:"required"`
BillingInterval BillingInterval `json:"billingInterval" validate:"required"`
BasePrice int64 `json:"basePrice" validate:"min=0"`
Currency string `json:"currency" validate:"len=3"`
TrialDays int `json:"trialDays" validate:"min=0,max=365"`
Features []PlanFeature `json:"features"`
PriceTiers []PriceTier `json:"priceTiers"`
TierMode TierMode `json:"tierMode"`
Metadata map[string]any `json:"metadata"`
IsActive bool `json:"isActive"`
IsPublic bool `json:"isPublic"`
DisplayOrder int `json:"displayOrder"`
}
CreatePlanRequest represents a request to create a new plan
type CreatePromotionCodeRequest ¶
type CreatePromotionCodeRequest struct {
CouponID xid.ID `json:"couponId" validate:"required"`
Code string `json:"code" validate:"required,min=3,max=50"`
MaxRedemptions int `json:"maxRedemptions"`
ValidFrom time.Time `json:"validFrom"`
ValidUntil *time.Time `json:"validUntil"`
RestrictToOrgs []string `json:"restrictToOrgs"`
FirstTimeOnly bool `json:"firstTimeOnly"`
}
CreatePromotionCodeRequest is used to create a promotion code
type CreateSubscriptionRequest ¶
type CreateSubscriptionRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
PlanID xid.ID `json:"planId" validate:"required"`
Quantity int `json:"quantity" validate:"min=1"`
StartTrial bool `json:"startTrial"`
TrialDays int `json:"trialDays" validate:"min=0,max=365"`
Metadata map[string]any `json:"metadata"`
}
CreateSubscriptionRequest represents a request to create a subscription
type CreateTaxExemptionRequest ¶
type CreateTaxExemptionRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
Type string `json:"type" validate:"required"`
Certificate string `json:"certificate" validate:"required"`
Country string `json:"country" validate:"required,len=2"`
State string `json:"state"`
ExpiresAt *time.Time `json:"expiresAt"`
}
CreateTaxExemptionRequest is used to create a tax exemption
type CreateTaxIDRequest ¶
type CreateTaxIDRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
Type TaxIDType `json:"type" validate:"required"`
Value string `json:"value" validate:"required"`
Country string `json:"country" validate:"required,len=2"`
}
CreateTaxIDRequest is used to create a customer tax ID
type CreateTaxRateRequest ¶
type CreateTaxRateRequest struct {
Name string `json:"name" validate:"required"`
Description string `json:"description"`
Type TaxType `json:"type" validate:"required"`
Percentage float64 `json:"percentage" validate:"required,gte=0,lte=100"`
Country string `json:"country" validate:"required,len=2"`
State string `json:"state"`
City string `json:"city"`
PostalCode string `json:"postalCode"`
Behavior TaxBehavior `json:"behavior" validate:"required"`
IsDefault bool `json:"isDefault"`
ValidFrom time.Time `json:"validFrom"`
}
CreateTaxRateRequest is used to create a new tax rate
type CurrencyAmount ¶
type CurrencyAmount struct {
Amount int64 `json:"amount"` // Amount in smallest unit (cents, pence, etc.)
Currency string `json:"currency"` // Currency code
DisplayValue string `json:"displayValue"` // Formatted display value
}
CurrencyAmount represents an amount in a specific currency
type Customer ¶
type Customer struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"`
ProviderCustomerID string `json:"providerCustomerId"` // Stripe Customer ID
Email string `json:"email"`
Name string `json:"name"`
Phone string `json:"phone"`
TaxID string `json:"taxId"` // VAT number, etc.
TaxExempt bool `json:"taxExempt"`
Currency string `json:"currency"` // Preferred currency
Balance int64 `json:"balance"` // Account balance in cents
DefaultPaymentID *xid.ID `json:"defaultPaymentId"` // Default payment method
BillingAddress *BillingAddress `json:"billingAddress"`
Metadata map[string]any `json:"metadata"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Customer represents the billing customer for an organization
type CustomerTaxID ¶
type CustomerTaxID struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
OrganizationID xid.ID `json:"organizationId"`
Type TaxIDType `json:"type"`
Value string `json:"value"`
Country string `json:"country"`
VerifiedAt *time.Time `json:"verifiedAt"`
IsValid bool `json:"isValid"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
CustomerTaxID represents a customer's tax identification
type DashboardMetrics ¶
type DashboardMetrics struct {
// Current state
TotalMRR int64 `json:"totalMrr"`
TotalARR int64 `json:"totalArr"`
ActiveSubscriptions int `json:"activeSubscriptions"`
TrialingSubscriptions int `json:"trialingSubscriptions"`
// Changes
MRRGrowth float64 `json:"mrrGrowth"` // Percentage change
SubscriptionGrowth float64 `json:"subscriptionGrowth"`
// Health indicators
ChurnRate float64 `json:"churnRate"`
TrialConversionRate float64 `json:"trialConversionRate"`
NetRevenueRetention float64 `json:"netRevenueRetention"`
// Revenue breakdown
NewMRR int64 `json:"newMrr"`
ExpansionMRR int64 `json:"expansionMrr"`
ChurnedMRR int64 `json:"churnedMrr"`
Currency string `json:"currency"`
AsOf time.Time `json:"asOf"`
}
DashboardMetrics provides overview metrics for the dashboard
type EventType ¶
type EventType string
EventType defines subscription-related event types
const ( // EventSubscriptionCreated when a subscription is created EventSubscriptionCreated EventType = "subscription.created" // EventSubscriptionUpdated when a subscription is updated EventSubscriptionUpdated EventType = "subscription.updated" // EventSubscriptionCanceled when a subscription is canceled EventSubscriptionCanceled EventType = "subscription.canceled" // EventSubscriptionPaused when a subscription is paused EventSubscriptionPaused EventType = "subscription.paused" // EventSubscriptionResumed when a subscription is resumed EventSubscriptionResumed EventType = "subscription.resumed" // EventSubscriptionTrialEnding when trial is about to end EventSubscriptionTrialEnding EventType = "subscription.trial_ending" // EventPaymentSucceeded when payment is successful EventPaymentSucceeded EventType = "payment.succeeded" // EventPaymentFailed when payment fails EventPaymentFailed EventType = "payment.failed" // EventInvoiceCreated when invoice is created EventInvoiceCreated EventType = "invoice.created" // EventInvoicePaid when invoice is paid EventInvoicePaid EventType = "invoice.paid" // EventUsageRecorded when usage is recorded EventUsageRecorded EventType = "usage.recorded" )
type ExchangeRate ¶
type ExchangeRate struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
FromCurrency string `json:"fromCurrency"` // Source currency code
ToCurrency string `json:"toCurrency"` // Target currency code
Rate float64 `json:"rate"` // Exchange rate (multiply by this to convert)
ValidFrom time.Time `json:"validFrom"` // When this rate becomes valid
ValidUntil *time.Time `json:"validUntil"` // When this rate expires (nil = current)
Source string `json:"source"` // Source of the rate (manual, api, etc.)
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
ExchangeRate represents a currency exchange rate
type ExportMetricsRequest ¶
type ExportMetricsRequest struct {
MetricTypes []MetricType `json:"metricTypes"`
Period MetricPeriod `json:"period"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
Format string `json:"format"` // csv, json, xlsx
}
ExportMetricsRequest is used to export metrics
type Feature ¶
type Feature struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
Key string `json:"key"` // Unique per app
Name string `json:"name"` // Display name
Description string `json:"description"` // Feature description
Type FeatureType `json:"type"` // boolean, limit, unlimited, metered, tiered
Unit string `json:"unit"` // "seats", "GB", "API calls", etc.
ResetPeriod ResetPeriod `json:"resetPeriod"` // When usage resets
IsPublic bool `json:"isPublic"` // Show in pricing pages
DisplayOrder int `json:"displayOrder"` // Order in UI
Icon string `json:"icon"` // Icon identifier for UI
Metadata map[string]any `json:"metadata"`
Tiers []FeatureTier `json:"tiers,omitempty"` // For tiered features
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Feature represents a standalone feature definition that can be linked to plans
func NewFeature ¶
func NewFeature(appID xid.ID, key, name string, featureType FeatureType) *Feature
NewFeature creates a new Feature with default values
type FeatureAccess ¶
type FeatureAccess struct {
Feature *Feature `json:"feature"`
HasAccess bool `json:"hasAccess"`
IsBlocked bool `json:"isBlocked"`
Limit int64 `json:"limit"` // -1 for unlimited, 0 for no access
CurrentUsage int64 `json:"currentUsage"`
Remaining int64 `json:"remaining"` // -1 for unlimited
GrantedExtra int64 `json:"grantedExtra"` // Extra from grants
PlanValue string `json:"planValue"` // The raw value from plan
}
FeatureAccess represents the complete access state for a feature
type FeatureGrant ¶
type FeatureGrant struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"`
FeatureID xid.ID `json:"featureId"`
FeatureKey string `json:"featureKey"` // Denormalized for convenience
GrantType FeatureGrantType `json:"grantType"` // addon, override, promotion, trial, manual
Value int64 `json:"value"` // Additional quota
ExpiresAt *time.Time `json:"expiresAt,omitempty"`
SourceType string `json:"sourceType,omitempty"` // addon, coupon, promotion, etc.
SourceID *xid.ID `json:"sourceId,omitempty"` // AddOn ID, Promotion ID, etc.
Reason string `json:"reason,omitempty"`
IsActive bool `json:"isActive"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
FeatureGrant provides additional feature access beyond the plan
type FeatureGrantType ¶
type FeatureGrantType string
FeatureGrantType defines the type of feature grant
const ( // FeatureGrantTypeAddon is a grant from an add-on purchase FeatureGrantTypeAddon FeatureGrantType = "addon" // FeatureGrantTypeOverride is a manual override FeatureGrantTypeOverride FeatureGrantType = "override" // FeatureGrantTypePromotion is a promotional grant FeatureGrantTypePromotion FeatureGrantType = "promotion" // FeatureGrantTypeTrial is a trial grant FeatureGrantTypeTrial FeatureGrantType = "trial" // FeatureGrantTypeManual is a manually added grant FeatureGrantTypeManual FeatureGrantType = "manual" )
func (FeatureGrantType) IsValid ¶
func (f FeatureGrantType) IsValid() bool
IsValid checks if the feature grant type is valid
func (FeatureGrantType) String ¶
func (f FeatureGrantType) String() string
String returns the string representation of the feature grant type
type FeatureTier ¶
type FeatureTier struct {
ID xid.ID `json:"id"`
FeatureID xid.ID `json:"featureId"`
TierOrder int `json:"tierOrder"`
UpTo int64 `json:"upTo"` // -1 for unlimited
Value string `json:"value"` // What's unlocked at this tier
Label string `json:"label"` // Display label for this tier
}
FeatureTier represents a tier within a tiered feature type
type FeatureType ¶
type FeatureType string
FeatureType defines the type of a plan feature
const ( // FeatureTypeBoolean is a simple on/off feature FeatureTypeBoolean FeatureType = "boolean" // FeatureTypeLimit is a numeric limit FeatureTypeLimit FeatureType = "limit" // FeatureTypeUnlimited is no limit on the feature FeatureTypeUnlimited FeatureType = "unlimited" // FeatureTypeMetered is a usage-based billing feature FeatureTypeMetered FeatureType = "metered" // FeatureTypeTiered provides different values at different usage levels FeatureTypeTiered FeatureType = "tiered" )
func (FeatureType) IsConsumable ¶
func (f FeatureType) IsConsumable() bool
IsConsumable returns true if the feature type can be consumed (has usage tracking)
func (FeatureType) IsValid ¶
func (f FeatureType) IsValid() bool
IsValid checks if the feature type is valid
func (FeatureType) String ¶
func (f FeatureType) String() string
String returns the string representation of the feature type
type FeatureUsageAction ¶
type FeatureUsageAction string
FeatureUsageAction defines the type of usage action
const ( // FeatureUsageActionConsume decrements the available quota FeatureUsageActionConsume FeatureUsageAction = "consume" // FeatureUsageActionGrant adds to the quota FeatureUsageActionGrant FeatureUsageAction = "grant" // FeatureUsageActionReset resets the usage counter FeatureUsageActionReset FeatureUsageAction = "reset" // FeatureUsageActionAdjust manually adjusts the usage FeatureUsageActionAdjust FeatureUsageAction = "adjust" )
func (FeatureUsageAction) IsValid ¶
func (f FeatureUsageAction) IsValid() bool
IsValid checks if the feature usage action is valid
func (FeatureUsageAction) String ¶
func (f FeatureUsageAction) String() string
String returns the string representation of the feature usage action
type FeatureUsageLog ¶
type FeatureUsageLog struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"`
FeatureID xid.ID `json:"featureId"`
FeatureKey string `json:"featureKey"`
Action string `json:"action"` // consume, grant, reset, adjust
Quantity int64 `json:"quantity"`
PreviousUsage int64 `json:"previousUsage"`
NewUsage int64 `json:"newUsage"`
ActorID *xid.ID `json:"actorId,omitempty"`
Reason string `json:"reason,omitempty"`
IdempotencyKey string `json:"idempotencyKey,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
CreatedAt time.Time `json:"createdAt"`
}
FeatureUsageLog represents an audit entry for feature usage changes
type FeatureUsageResponse ¶
type FeatureUsageResponse struct {
FeatureKey string `json:"featureKey"`
FeatureName string `json:"featureName"`
FeatureType string `json:"featureType"`
CurrentUsage int64 `json:"currentUsage"`
Limit int64 `json:"limit"` // -1 for unlimited
Remaining int64 `json:"remaining"` // -1 for unlimited
PeriodStart time.Time `json:"periodStart"`
PeriodEnd time.Time `json:"periodEnd"`
GrantedExtra int64 `json:"grantedExtra"` // Extra quota from grants
}
FeatureUsageResponse represents the response for feature usage queries
type GetCohortAnalysisRequest ¶
type GetCohortAnalysisRequest struct {
StartMonth time.Time `json:"startMonth"`
NumMonths int `json:"numMonths"`
Currency string `json:"currency"`
}
GetCohortAnalysisRequest is used to request cohort analysis
type GetMetricsRequest ¶
type GetMetricsRequest struct {
MetricTypes []MetricType `json:"metricTypes"`
Period MetricPeriod `json:"period"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
Currency string `json:"currency"`
GroupBy string `json:"groupBy"` // plan, segment, etc.
}
GetMetricsRequest is used to request billing metrics
type GetUsageSummaryRequest ¶
type GetUsageSummaryRequest struct {
SubscriptionID xid.ID `json:"subscriptionId" validate:"required"`
MetricKey string `json:"metricKey" validate:"required"`
PeriodStart time.Time `json:"periodStart" validate:"required"`
PeriodEnd time.Time `json:"periodEnd" validate:"required"`
}
GetUsageSummaryRequest represents a request to get usage summary
type GrantFeatureRequest ¶
type GrantFeatureRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
FeatureKey string `json:"featureKey" validate:"required"`
GrantType FeatureGrantType `json:"grantType" validate:"required"`
Value int64 `json:"value" validate:"required,min=1"`
ExpiresAt *time.Time `json:"expiresAt,omitempty"`
SourceType string `json:"sourceType,omitempty"`
SourceID *xid.ID `json:"sourceId,omitempty"`
Reason string `json:"reason,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
GrantFeatureRequest represents a request to grant additional feature quota
type Invoice ¶
type Invoice struct {
ID xid.ID `json:"id"`
SubscriptionID xid.ID `json:"subscriptionId"` // Related subscription
OrganizationID xid.ID `json:"organizationId"` // Organization billed
Number string `json:"number"` // Invoice number (e.g., INV-2024-0001)
Status InvoiceStatus `json:"status"` // Current status
Currency string `json:"currency"` // ISO 4217 currency code
Subtotal int64 `json:"subtotal"` // Amount before tax in cents
Tax int64 `json:"tax"` // Tax amount in cents
Total int64 `json:"total"` // Total amount in cents
AmountPaid int64 `json:"amountPaid"` // Amount already paid in cents
AmountDue int64 `json:"amountDue"` // Remaining amount due in cents
Description string `json:"description"` // Invoice description
PeriodStart time.Time `json:"periodStart"` // Billing period start
PeriodEnd time.Time `json:"periodEnd"` // Billing period end
DueDate time.Time `json:"dueDate"` // Payment due date
PaidAt *time.Time `json:"paidAt"` // When paid
VoidedAt *time.Time `json:"voidedAt"` // When voided
ProviderInvoiceID string `json:"providerInvoiceId"` // Stripe Invoice ID
ProviderPDFURL string `json:"providerPdfUrl"` // Stripe hosted PDF URL
HostedInvoiceURL string `json:"hostedInvoiceUrl"` // Stripe hosted invoice page
Metadata map[string]any `json:"metadata"` // Custom metadata
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// Relations
Items []InvoiceItem `json:"items,omitempty"`
}
Invoice represents a billing invoice
func NewInvoice ¶
NewInvoice creates a new Invoice with default values
func (*Invoice) AddItem ¶
func (i *Invoice) AddItem(description string, quantity, unitAmount int64) *InvoiceItem
AddItem adds a line item to the invoice
func (*Invoice) Finalize ¶
func (i *Invoice) Finalize()
Finalize moves the invoice from draft to open
type InvoiceItem ¶
type InvoiceItem struct {
ID xid.ID `json:"id"`
InvoiceID xid.ID `json:"invoiceId"`
Description string `json:"description"` // Line item description
Quantity int64 `json:"quantity"` // Quantity
UnitAmount int64 `json:"unitAmount"` // Unit price in cents
Amount int64 `json:"amount"` // Total amount in cents
PlanID *xid.ID `json:"planId"` // Related plan if applicable
AddOnID *xid.ID `json:"addOnId"` // Related add-on if applicable
PeriodStart time.Time `json:"periodStart"` // Item period start
PeriodEnd time.Time `json:"periodEnd"` // Item period end
Proration bool `json:"proration"` // Is this a proration adjustment
Metadata map[string]any `json:"metadata"` // Custom metadata
ProviderItemID string `json:"providerItemId"` // Stripe Invoice Item ID
CreatedAt time.Time `json:"createdAt"`
}
InvoiceItem represents a line item on an invoice
type InvoiceMetrics ¶
type InvoiceMetrics struct {
Period MetricPeriod `json:"period"`
TotalInvoiced int64 `json:"totalInvoiced"`
TotalCollected int64 `json:"totalCollected"`
TotalOutstanding int64 `json:"totalOutstanding"`
TotalOverdue int64 `json:"totalOverdue"`
CollectionRate float64 `json:"collectionRate"` // Percentage
AverageTimeToPayment float64 `json:"averageTimeToPayment"` // In days
Currency string `json:"currency"`
}
InvoiceMetrics provides invoice and payment metrics
type InvoiceStatus ¶
type InvoiceStatus string
InvoiceStatus defines the state of an invoice
const ( // InvoiceStatusDraft is not yet finalized InvoiceStatusDraft InvoiceStatus = "draft" // InvoiceStatusOpen is awaiting payment InvoiceStatusOpen InvoiceStatus = "open" // InvoiceStatusPaid has been paid InvoiceStatusPaid InvoiceStatus = "paid" // InvoiceStatusVoid has been voided InvoiceStatusVoid InvoiceStatus = "void" // InvoiceStatusUncollectible cannot be collected InvoiceStatusUncollectible InvoiceStatus = "uncollectible" )
func (InvoiceStatus) IsValid ¶
func (i InvoiceStatus) IsValid() bool
IsValid checks if the invoice status is valid
func (InvoiceStatus) String ¶
func (i InvoiceStatus) String() string
String returns the string representation of the invoice status
type LinkFeatureRequest ¶
type LinkFeatureRequest struct {
FeatureID xid.ID `json:"featureId" validate:"required"`
Value string `json:"value"` // The limit/value for this plan
IsBlocked bool `json:"isBlocked"` // Explicitly block this feature
IsHighlighted bool `json:"isHighlighted"` // Highlight in pricing UI
OverrideSettings map[string]any `json:"overrideSettings,omitempty"`
}
LinkFeatureRequest represents a request to link a feature to a plan
type ListInvoicesFilter ¶
type ListInvoicesFilter struct {
OrganizationID *xid.ID `json:"organizationId"`
SubscriptionID *xid.ID `json:"subscriptionId"`
Status InvoiceStatus `json:"status"`
FromDate *time.Time `json:"fromDate"`
ToDate *time.Time `json:"toDate"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
ListInvoicesFilter defines filters for listing invoices
type ListUsageRecordsFilter ¶
type ListUsageRecordsFilter struct {
SubscriptionID *xid.ID `json:"subscriptionId"`
OrganizationID *xid.ID `json:"organizationId"`
MetricKey string `json:"metricKey"`
FromDate *time.Time `json:"fromDate"`
ToDate *time.Time `json:"toDate"`
Reported *bool `json:"reported"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
}
ListUsageRecordsFilter defines filters for listing usage records
type MRRBreakdown ¶
type MRRBreakdown struct {
Date time.Time `json:"date"`
Currency string `json:"currency"`
TotalMRR int64 `json:"totalMrr"`
NewMRR int64 `json:"newMrr"` // From new customers
ExpansionMRR int64 `json:"expansionMrr"` // From upgrades
ContractionMRR int64 `json:"contractionMrr"` // From downgrades (negative)
ChurnedMRR int64 `json:"churnedMrr"` // Lost from cancellations (negative)
ReactivationMRR int64 `json:"reactivationMrr"` // From reactivated customers
NetNewMRR int64 `json:"netNewMrr"` // Total change
}
MRRBreakdown provides a detailed breakdown of MRR
type MetricPeriod ¶
type MetricPeriod string
MetricPeriod represents the time period for metrics
const ( MetricPeriodDaily MetricPeriod = "daily" MetricPeriodWeekly MetricPeriod = "weekly" MetricPeriodMonthly MetricPeriod = "monthly" MetricPeriodYearly MetricPeriod = "yearly" )
type MetricType ¶
type MetricType string
MetricType represents the type of billing metric
const ( MetricTypeMRR MetricType = "mrr" // Monthly Recurring Revenue MetricTypeARR MetricType = "arr" // Annual Recurring Revenue MetricTypeChurnRate MetricType = "churn_rate" // Customer churn rate MetricTypeRevenueChurn MetricType = "revenue_churn" // Revenue churn rate MetricTypeExpansionMRR MetricType = "expansion_mrr" // Expansion MRR (upgrades) MetricTypeContractionMRR MetricType = "contraction_mrr" // Contraction MRR (downgrades) MetricTypeNewMRR MetricType = "new_mrr" // New customer MRR MetricTypeLTV MetricType = "ltv" // Customer Lifetime Value MetricTypeCAC MetricType = "cac" // Customer Acquisition Cost MetricTypeARPU MetricType = "arpu" // Average Revenue Per User MetricTypeTrialConversion MetricType = "trial_conversion" // Trial to paid conversion rate MetricTypeNetRevenue MetricType = "net_revenue" // Net revenue retention )
type MetricsResponse ¶
type MetricsResponse struct {
Metrics []BillingMetric `json:"metrics"`
MRRHistory []MRRBreakdown `json:"mrrHistory,omitempty"`
Churn *ChurnAnalysis `json:"churn,omitempty"`
Dashboard *DashboardMetrics `json:"dashboard,omitempty"`
StartDate time.Time `json:"startDate"`
EndDate time.Time `json:"endDate"`
Currency string `json:"currency"`
}
MetricsResponse contains the metrics response
type MultiCurrencyPrice ¶
type MultiCurrencyPrice struct {
BaseCurrency string `json:"baseCurrency"`
BaseAmount int64 `json:"baseAmount"`
Prices map[string]CurrencyAmount `json:"prices"` // Currency code -> amount
}
MultiCurrencyPrice represents a price in multiple currencies
type OrganizationFeatureUsage ¶
type OrganizationFeatureUsage struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"`
FeatureID xid.ID `json:"featureId"`
FeatureKey string `json:"featureKey"` // Denormalized for convenience
CurrentUsage int64 `json:"currentUsage"`
PeriodStart time.Time `json:"periodStart"`
PeriodEnd time.Time `json:"periodEnd"`
LastReset time.Time `json:"lastReset"`
Metadata map[string]any `json:"metadata,omitempty"`
}
OrganizationFeatureUsage tracks feature usage per organization
type PauseSubscriptionRequest ¶
type PauseSubscriptionRequest struct {
ResumeAt *time.Time `json:"resumeAt"` // Optional date to auto-resume
Reason string `json:"reason"` // Pause reason
}
PauseSubscriptionRequest represents a request to pause a subscription
type PaymentMethod ¶
type PaymentMethod struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"`
Type PaymentMethodType `json:"type"` // card, bank_account, etc.
IsDefault bool `json:"isDefault"` // Is this the default payment method
ProviderMethodID string `json:"providerMethodId"` // Stripe PaymentMethod ID
ProviderCustomerID string `json:"providerCustomerId"` // Stripe Customer ID
// Card-specific fields (when Type == PaymentMethodCard)
CardBrand string `json:"cardBrand"` // visa, mastercard, etc.
CardLast4 string `json:"cardLast4"` // Last 4 digits
CardExpMonth int `json:"cardExpMonth"` // Expiration month
CardExpYear int `json:"cardExpYear"` // Expiration year
CardFunding string `json:"cardFunding"` // credit, debit, prepaid
// Bank account specific fields (when Type == PaymentMethodBankAccount)
BankName string `json:"bankName"`
BankLast4 string `json:"bankLast4"`
BankRoutingNumber string `json:"bankRoutingNumber"` // Masked
BankAccountType string `json:"bankAccountType"` // checking, savings
// Billing details
BillingName string `json:"billingName"`
BillingEmail string `json:"billingEmail"`
BillingPhone string `json:"billingPhone"`
BillingAddressLine1 string `json:"billingAddressLine1"`
BillingAddressLine2 string `json:"billingAddressLine2"`
BillingCity string `json:"billingCity"`
BillingState string `json:"billingState"`
BillingPostalCode string `json:"billingPostalCode"`
BillingCountry string `json:"billingCountry"`
Metadata map[string]any `json:"metadata"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
PaymentMethod represents a stored payment method
func NewPaymentMethod ¶
func NewPaymentMethod(orgID xid.ID, methodType PaymentMethodType) *PaymentMethod
NewPaymentMethod creates a new PaymentMethod with default values
func (*PaymentMethod) DisplayName ¶
func (pm *PaymentMethod) DisplayName() string
DisplayName returns a user-friendly display name for the payment method
func (*PaymentMethod) IsBankAccount ¶
func (pm *PaymentMethod) IsBankAccount() bool
IsBankAccount returns true if this is a bank account
func (*PaymentMethod) IsCard ¶
func (pm *PaymentMethod) IsCard() bool
IsCard returns true if this is a card payment method
func (*PaymentMethod) IsExpired ¶
func (pm *PaymentMethod) IsExpired() bool
IsExpired returns true if the card is expired
func (*PaymentMethod) WillExpireSoon ¶
func (pm *PaymentMethod) WillExpireSoon(days int) bool
WillExpireSoon returns true if the card will expire within the given days
type PaymentMethodType ¶
type PaymentMethodType string
PaymentMethodType defines the type of payment method
const ( // PaymentMethodCard is a credit/debit card PaymentMethodCard PaymentMethodType = "card" // PaymentMethodBankAccount is a bank account PaymentMethodBankAccount PaymentMethodType = "bank_account" // PaymentMethodSepaDebit is SEPA direct debit PaymentMethodSepaDebit PaymentMethodType = "sepa_debit" )
func (PaymentMethodType) IsValid ¶
func (p PaymentMethodType) IsValid() bool
IsValid checks if the payment method type is valid
func (PaymentMethodType) String ¶
func (p PaymentMethodType) String() string
String returns the string representation of the payment method type
type Plan ¶
type Plan struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"` // Scoped to app
Name string `json:"name"` // Display name
Slug string `json:"slug"` // URL-safe identifier
Description string `json:"description"` // Marketing description
Archived bool `json:"archived"` // Whether the plan is archived
BillingPattern BillingPattern `json:"billingPattern"` // How the plan is billed
BillingInterval BillingInterval `json:"billingInterval"` // Billing frequency
BasePrice int64 `json:"basePrice"` // Price in cents
Currency string `json:"currency"` // ISO 4217 currency code
TrialDays int `json:"trialDays"` // Number of trial days (0 for no trial)
Features []PlanFeature `json:"features"` // Feature flags and limits
PriceTiers []PriceTier `json:"priceTiers"` // For tiered/usage pricing
TierMode TierMode `json:"tierMode"` // How tiers are applied
Metadata map[string]any `json:"metadata"` // Custom metadata
IsActive bool `json:"isActive"` // Can be subscribed to
IsPublic bool `json:"isPublic"` // Visible in public pricing
DisplayOrder int `json:"displayOrder"` // Order in pricing pages
ProviderPlanID string `json:"providerPlanId"` // Stripe Product ID
ProviderPriceID string `json:"providerPriceId"` // Stripe Price ID
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
Plan represents a subscription plan that organizations can subscribe to
func (*Plan) AddPriceTier ¶
AddPriceTier adds a pricing tier to the plan
func (*Plan) CalculateTieredPrice ¶
CalculateTieredPrice calculates the price for a given quantity using tiered pricing
func (*Plan) GetFeature ¶
func (p *Plan) GetFeature(key string) *PlanFeature
GetFeature returns a feature by key, or nil if not found
func (*Plan) GetFeatureLimit ¶
GetFeatureLimit returns the numeric limit for a feature, or -1 if unlimited
func (*Plan) HasFeature ¶
HasFeature checks if a plan has a specific feature enabled
func (*Plan) SetFeature ¶
func (p *Plan) SetFeature(key, name string, featureType FeatureType, value any)
SetFeature adds or updates a feature on the plan
type PlanFeature ¶
type PlanFeature struct {
Key string `json:"key"` // Feature identifier (e.g., "max_members")
Name string `json:"name"` // Display name
Description string `json:"description"` // Feature description
Type FeatureType `json:"type"` // boolean, limit, or unlimited
Value any `json:"value"` // The feature value (true, 100, -1 for unlimited)
Unit string `json:"unit,omitempty"` // Unit of measurement (e.g., "seats", "GB", "API calls")
IsHighlighted bool `json:"isHighlighted,omitempty"` // Highlight in pricing comparison
}
PlanFeature represents a feature or limit included in a plan
type PlanFeatureLink ¶
type PlanFeatureLink struct {
ID xid.ID `json:"id"`
PlanID xid.ID `json:"planId"`
FeatureID xid.ID `json:"featureId"`
Value string `json:"value"` // JSON: limit value, tier, boolean, etc.
IsBlocked bool `json:"isBlocked"` // Explicitly blocked for this plan
IsHighlighted bool `json:"isHighlighted"` // Highlight in pricing comparison
OverrideSettings map[string]any `json:"overrideSettings,omitempty"`
Feature *Feature `json:"feature,omitempty"` // Loaded feature
}
PlanFeatureLink connects features to plans with plan-specific configuration
type PriceTier ¶
type PriceTier struct {
UpTo int64 `json:"upTo"` // Upper bound (-1 for infinite)
UnitAmount int64 `json:"unitAmount"` // Price per unit in cents
FlatAmount int64 `json:"flatAmount"` // Flat fee for this tier in cents
}
PriceTier represents a pricing tier for tiered or usage-based billing
type PromotionCode ¶
type PromotionCode struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
CouponID xid.ID `json:"couponId"`
Coupon *Coupon `json:"coupon,omitempty"`
Code string `json:"code"` // Unique promotion code
IsActive bool `json:"isActive"`
// Restrictions (override coupon settings)
MaxRedemptions int `json:"maxRedemptions"` // Max for this specific code
ValidFrom time.Time `json:"validFrom"`
ValidUntil *time.Time `json:"validUntil"`
// Customer restrictions
RestrictToOrgs []string `json:"restrictToOrgs"` // Org IDs that can use this
FirstTimeOnly bool `json:"firstTimeOnly"`
// Usage tracking
TimesRedeemed int `json:"timesRedeemed"`
// Provider integration
ProviderPromoID string `json:"providerPromoId"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
PromotionCode represents a promotion code that references a coupon This allows multiple codes to reference the same underlying coupon
type PublicFeature ¶
type PublicFeature struct {
Key string `json:"key"`
Name string `json:"name"`
Description string `json:"description"`
Type string `json:"type"`
Unit string `json:"unit,omitempty"`
Icon string `json:"icon,omitempty"`
DisplayOrder int `json:"displayOrder"`
}
PublicFeature represents a feature for public API (pricing pages)
type PublicPlanFeature ¶
type PublicPlanFeature struct {
Key string `json:"key"`
Name string `json:"name"`
Description string `json:"description"`
Type string `json:"type"`
Unit string `json:"unit,omitempty"`
Value any `json:"value"` // Parsed value (boolean, number, or tier info)
IsHighlighted bool `json:"isHighlighted"`
IsBlocked bool `json:"isBlocked"`
DisplayOrder int `json:"displayOrder"`
}
PublicPlanFeature represents a feature within a plan for public API
type RecordUsageRequest ¶
type RecordUsageRequest struct {
SubscriptionID xid.ID `json:"subscriptionId" validate:"required"`
MetricKey string `json:"metricKey" validate:"required,min=1,max=50"`
Quantity int64 `json:"quantity" validate:"required,min=0"`
Action UsageAction `json:"action" validate:"required"`
Timestamp *time.Time `json:"timestamp"` // Optional, defaults to now
IdempotencyKey string `json:"idempotencyKey" validate:"max=100"`
Metadata map[string]any `json:"metadata"`
}
RecordUsageRequest represents a request to record usage
type RedeemCouponRequest ¶
type RedeemCouponRequest struct {
Code string `json:"code" validate:"required"`
OrganizationID xid.ID `json:"organizationId" validate:"required"`
SubscriptionID xid.ID `json:"subscriptionId" validate:"required"`
}
RedeemCouponRequest is used to redeem a coupon
type ResetPeriod ¶
type ResetPeriod string
ResetPeriod defines when feature usage should be reset
const ( // ResetPeriodNone means usage never resets (cumulative) ResetPeriodNone ResetPeriod = "none" // ResetPeriodDaily resets usage every day ResetPeriodDaily ResetPeriod = "daily" // ResetPeriodWeekly resets usage every week ResetPeriodWeekly ResetPeriod = "weekly" // ResetPeriodMonthly resets usage every month ResetPeriodMonthly ResetPeriod = "monthly" // ResetPeriodYearly resets usage every year ResetPeriodYearly ResetPeriod = "yearly" // ResetPeriodBillingCycle resets usage at each billing cycle ResetPeriodBillingCycle ResetPeriod = "billing_period" )
func (ResetPeriod) IsValid ¶
func (r ResetPeriod) IsValid() bool
IsValid checks if the reset period is valid
func (ResetPeriod) String ¶
func (r ResetPeriod) String() string
String returns the string representation of the reset period
type ResolveAlertRequest ¶
type ResolveAlertRequest struct {
AlertID xid.ID `json:"alertId" validate:"required"`
Resolution string `json:"resolution"`
}
ResolveAlertRequest is used to resolve an alert
type RevenueByPlan ¶
type RevenueByPlan struct {
PlanID xid.ID `json:"planId"`
PlanName string `json:"planName"`
PlanSlug string `json:"planSlug"`
ActiveSubscribers int `json:"activeSubscribers"`
MRR int64 `json:"mrr"`
ARR int64 `json:"arr"`
PercentOfTotal float64 `json:"percentOfTotal"`
Currency string `json:"currency"`
}
RevenueByPlan shows revenue breakdown by plan
type RevenueBySegment ¶
type RevenueBySegment struct {
Segment string `json:"segment"`
Subscribers int `json:"subscribers"`
MRR int64 `json:"mrr"`
ARPU int64 `json:"arpu"`
ChurnRate float64 `json:"churnRate"`
LTV int64 `json:"ltv"`
Currency string `json:"currency"`
}
RevenueBySegment shows revenue by customer segment
type SetupIntentResult ¶
type SetupIntentResult struct {
ClientSecret string `json:"clientSecret"` // For client-side confirmation
SetupIntentID string `json:"setupIntentId"` // Stripe SetupIntent ID
PublishableKey string `json:"publishableKey"` // Stripe publishable key
}
SetupIntentResult represents the result of creating a setup intent
type SnoozeAlertRequest ¶
type SnoozeAlertRequest struct {
AlertID xid.ID `json:"alertId" validate:"required"`
SnoozeUntil time.Time `json:"snoozeUntil" validate:"required"`
}
SnoozeAlertRequest is used to snooze an alert
type StripeConfig ¶
type StripeConfig struct {
SecretKey string `json:"secretKey"`
WebhookSecret string `json:"webhookSecret"`
PublishableKey string `json:"publishableKey"`
APIVersion string `json:"apiVersion"` // Optional: specific API version
ConnectAccount string `json:"connectAccount"` // Optional: for Stripe Connect
}
StripeConfig holds Stripe-specific configuration
type Subscription ¶
type Subscription struct {
ID xid.ID `json:"id"`
OrganizationID xid.ID `json:"organizationId"` // Links to Organization
PlanID xid.ID `json:"planId"` // Current plan
Status SubscriptionStatus `json:"status"` // Current status
Quantity int `json:"quantity"` // For per-seat billing
CurrentPeriodStart time.Time `json:"currentPeriodStart"` // Start of current billing period
CurrentPeriodEnd time.Time `json:"currentPeriodEnd"` // End of current billing period
TrialStart *time.Time `json:"trialStart"` // Start of trial
TrialEnd *time.Time `json:"trialEnd"` // End of trial
CancelAt *time.Time `json:"cancelAt"` // Scheduled cancellation date
CanceledAt *time.Time `json:"canceledAt"` // When cancellation was requested
EndedAt *time.Time `json:"endedAt"` // When subscription actually ended
PausedAt *time.Time `json:"pausedAt"` // When subscription was paused
ResumeAt *time.Time `json:"resumeAt"` // Scheduled resume date
ProviderSubID string `json:"providerSubId"` // Stripe Subscription ID
ProviderCustomerID string `json:"providerCustomerId"` // Stripe Customer ID
Metadata map[string]any `json:"metadata"` // Custom metadata
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
// Relations (populated when loaded)
Plan *Plan `json:"plan,omitempty"`
AddOns []SubscriptionAddOn `json:"addOns,omitempty"`
}
Subscription represents an organization's subscription to a plan
func NewSubscription ¶
func NewSubscription(orgID, planID xid.ID) *Subscription
NewSubscription creates a new Subscription with default values
func (*Subscription) ActivateFromTrial ¶
func (s *Subscription) ActivateFromTrial()
ActivateFromTrial converts trial to active subscription
func (*Subscription) Cancel ¶
func (s *Subscription) Cancel(immediate bool)
Cancel marks the subscription for cancellation
func (*Subscription) DaysUntilRenewal ¶
func (s *Subscription) DaysUntilRenewal() int
DaysUntilRenewal returns the number of days until the next billing date
func (*Subscription) DaysUntilTrialEnd ¶
func (s *Subscription) DaysUntilTrialEnd() int
DaysUntilTrialEnd returns the number of days until trial ends, or -1 if not trialing
func (*Subscription) IsActive ¶
func (s *Subscription) IsActive() bool
IsActive returns true if the subscription is currently usable
func (*Subscription) IsCanceled ¶
func (s *Subscription) IsCanceled() bool
IsCanceled returns true if the subscription has been canceled
func (*Subscription) IsPastDue ¶
func (s *Subscription) IsPastDue() bool
IsPastDue returns true if payment has failed
func (*Subscription) IsPaused ¶
func (s *Subscription) IsPaused() bool
IsPaused returns true if the subscription is paused
func (*Subscription) IsTrialing ¶
func (s *Subscription) IsTrialing() bool
IsTrialing returns true if the subscription is in trial
func (*Subscription) Pause ¶
func (s *Subscription) Pause(resumeAt *time.Time)
Pause pauses the subscription
func (*Subscription) StartTrial ¶
func (s *Subscription) StartTrial(days int)
StartTrial starts a trial period
func (*Subscription) WillCancel ¶
func (s *Subscription) WillCancel() bool
WillCancel returns true if the subscription is scheduled to cancel
type SubscriptionAddOn ¶
type SubscriptionAddOn struct {
ID xid.ID `json:"id"`
SubscriptionID xid.ID `json:"subscriptionId"`
AddOnID xid.ID `json:"addOnId"`
Quantity int `json:"quantity"`
ProviderSubItemID string `json:"providerSubItemId"` // Stripe Subscription Item ID
CreatedAt time.Time `json:"createdAt"`
// Relations
AddOn *AddOn `json:"addOn,omitempty"`
}
SubscriptionAddOn represents an add-on attached to a subscription
type SubscriptionMovement ¶
type SubscriptionMovement struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
SubscriptionID xid.ID `json:"subscriptionId"`
OrganizationID xid.ID `json:"organizationId"`
MovementType string `json:"movementType"` // new, upgrade, downgrade, churn, reactivation
// Revenue impact
PreviousMRR int64 `json:"previousMrr"`
NewMRR int64 `json:"newMrr"`
MRRChange int64 `json:"mrrChange"`
Currency string `json:"currency"`
// Plan details
PreviousPlanID *xid.ID `json:"previousPlanId"`
NewPlanID *xid.ID `json:"newPlanId"`
// Metadata
Reason string `json:"reason"`
Notes string `json:"notes"`
OccurredAt time.Time `json:"occurredAt"`
CreatedAt time.Time `json:"createdAt"`
}
SubscriptionMovement tracks subscription changes
type SubscriptionStatus ¶
type SubscriptionStatus string
SubscriptionStatus defines the current state of a subscription
const ( // StatusTrialing is an active trial period StatusTrialing SubscriptionStatus = "trialing" // StatusActive is a paid, active subscription StatusActive SubscriptionStatus = "active" // StatusPastDue has failed payment but still active StatusPastDue SubscriptionStatus = "past_due" // StatusCanceled has been cancelled StatusCanceled SubscriptionStatus = "canceled" // StatusUnpaid has exhausted retry attempts StatusUnpaid SubscriptionStatus = "unpaid" // StatusPaused is temporarily paused StatusPaused SubscriptionStatus = "paused" // StatusIncomplete requires payment action to activate StatusIncomplete SubscriptionStatus = "incomplete" )
func (SubscriptionStatus) IsActiveOrTrialing ¶
func (s SubscriptionStatus) IsActiveOrTrialing() bool
IsActiveOrTrialing returns true if the subscription is usable
func (SubscriptionStatus) IsValid ¶
func (s SubscriptionStatus) IsValid() bool
IsValid checks if the subscription status is valid
func (SubscriptionStatus) String ¶
func (s SubscriptionStatus) String() string
String returns the string representation of the subscription status
type SupportedCurrency ¶
type SupportedCurrency struct {
ID xid.ID `json:"id"`
Code string `json:"code"` // ISO 4217 code (USD, EUR, GBP, etc.)
Name string `json:"name"` // Display name
Symbol string `json:"symbol"` // Currency symbol ($, €, £)
DecimalPlaces int `json:"decimalPlaces"` // Number of decimal places (2 for most, 0 for JPY)
IsDefault bool `json:"isDefault"` // Is this the default currency
IsActive bool `json:"isActive"` // Is this currency currently active
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
SupportedCurrency represents a currency supported by the system
func DefaultCurrencies ¶
func DefaultCurrencies() []SupportedCurrency
DefaultCurrencies returns the default supported currencies
type TaxBehavior ¶
type TaxBehavior string
TaxBehavior defines how tax is applied to prices
const ( TaxBehaviorExclusive TaxBehavior = "exclusive" // Tax added on top of price TaxBehaviorInclusive TaxBehavior = "inclusive" // Tax included in price )
type TaxBillingAddress ¶
type TaxBillingAddress = BillingAddress
TaxBillingAddress represents a customer's billing address for tax purposes Note: Uses BillingAddress from payment.go for actual address storage This alias is for documentation purposes
type TaxCalculation ¶
type TaxCalculation struct {
TaxRateID xid.ID `json:"taxRateId"`
TaxRateName string `json:"taxRateName"`
TaxType TaxType `json:"taxType"`
Percentage float64 `json:"percentage"`
TaxableAmount int64 `json:"taxableAmount"` // Amount before tax
TaxAmount int64 `json:"taxAmount"` // Calculated tax amount
TotalAmount int64 `json:"totalAmount"` // Amount after tax
Currency string `json:"currency"`
IsExempt bool `json:"isExempt"`
ExemptionID *xid.ID `json:"exemptionId"`
}
TaxCalculation represents a calculated tax amount
type TaxExemption ¶
type TaxExemption struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
OrganizationID xid.ID `json:"organizationId"`
Type string `json:"type"` // Exemption type (nonprofit, government, resale)
Certificate string `json:"certificate"` // Exemption certificate number
Country string `json:"country"` // Country where exemption applies
State string `json:"state"` // State where exemption applies
VerifiedAt *time.Time `json:"verifiedAt"` // When exemption was verified
ExpiresAt *time.Time `json:"expiresAt"` // When exemption expires
IsActive bool `json:"isActive"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
TaxExemption represents a tax exemption for an organization
type TaxIDType ¶
type TaxIDType string
TaxIDType represents the type of tax ID
const ( TaxIDTypeVAT TaxIDType = "eu_vat" TaxIDTypeGSTIN TaxIDType = "in_gst" TaxIDTypeABN TaxIDType = "au_abn" TaxIDTypeGST_NZ TaxIDType = "nz_gst" TaxIDTypeEIN TaxIDType = "us_ein" TaxIDTypeGST_CA TaxIDType = "ca_gst" TaxIDTypeBN TaxIDType = "ca_bn" TaxIDTypeCNPJ TaxIDType = "br_cnpj" TaxIDTypeCPF TaxIDType = "br_cpf" TaxIDTypeCustom TaxIDType = "custom" )
type TaxRate ¶
type TaxRate struct {
ID xid.ID `json:"id"`
AppID xid.ID `json:"appId"`
Name string `json:"name"` // Display name (e.g., "US Sales Tax", "UK VAT")
Description string `json:"description"` // Optional description
Type TaxType `json:"type"` // Type of tax
Percentage float64 `json:"percentage"` // Tax rate as percentage (e.g., 20.0 for 20%)
Country string `json:"country"` // ISO 3166-1 alpha-2 country code
State string `json:"state"` // State/province code (for US, CA)
City string `json:"city"` // City (for local taxes)
PostalCode string `json:"postalCode"` // Postal/ZIP code pattern
Behavior TaxBehavior `json:"behavior"` // Exclusive or inclusive
IsDefault bool `json:"isDefault"` // Default rate for the region
IsActive bool `json:"isActive"` // Is this rate active
// Provider integration
ProviderTaxRateID string `json:"providerTaxRateId"` // Tax rate ID in payment provider
// Timestamps
ValidFrom time.Time `json:"validFrom"` // When rate becomes valid
ValidUntil *time.Time `json:"validUntil"` // When rate expires
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
TaxRate represents a tax rate configuration
type TaxSummary ¶
type TaxSummary struct {
Calculations []TaxCalculation `json:"calculations"`
TotalTax int64 `json:"totalTax"`
Currency string `json:"currency"`
}
TaxSummary represents a summary of taxes on an invoice
type TaxType ¶
type TaxType string
TaxType represents the type of tax
const ( TaxTypeVAT TaxType = "vat" // Value Added Tax (EU, UK) TaxTypeGST TaxType = "gst" // Goods and Services Tax (AU, NZ, IN) TaxTypeSalesTax TaxType = "sales_tax" // Sales Tax (US) TaxTypeHST TaxType = "hst" // Harmonized Sales Tax (Canada) TaxTypePST TaxType = "pst" // Provincial Sales Tax (Canada) TaxTypeConsumption TaxType = "consumption" // Consumption Tax (JP) TaxTypeCustom TaxType = "custom" // Custom tax type )
type TrialMetrics ¶
type TrialMetrics struct {
Period MetricPeriod `json:"period"`
TrialsStarted int `json:"trialsStarted"`
TrialsConverted int `json:"trialsConverted"`
TrialsExpired int `json:"trialsExpired"`
TrialsActive int `json:"trialsActive"`
ConversionRate float64 `json:"conversionRate"`
AverageTrialLength float64 `json:"averageTrialLength"` // In days
// Conversion by plan
ConversionByPlan map[string]float64 `json:"conversionByPlan"` // Plan slug -> rate
}
TrialMetrics provides trial conversion metrics
type TriggerAlertRequest ¶
type TriggerAlertRequest struct {
OrganizationID xid.ID `json:"organizationId" validate:"required"`
Type AlertType `json:"type" validate:"required"`
Severity AlertSeverity `json:"severity"`
Title string `json:"title" validate:"required"`
Message string `json:"message" validate:"required"`
Metadata map[string]interface{} `json:"metadata"`
}
TriggerAlertRequest is used to manually trigger an alert
type UpdateAddOnRequest ¶
type UpdateAddOnRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
Price *int64 `json:"price,omitempty" validate:"omitempty,min=0"`
Features []PlanFeature `json:"features,omitempty"`
PriceTiers []PriceTier `json:"priceTiers,omitempty"`
TierMode *TierMode `json:"tierMode,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
IsActive *bool `json:"isActive,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
DisplayOrder *int `json:"displayOrder,omitempty"`
RequiresPlanIDs []xid.ID `json:"requiresPlanIds,omitempty"`
ExcludesPlanIDs []xid.ID `json:"excludesPlanIds,omitempty"`
MaxQuantity *int `json:"maxQuantity,omitempty"`
}
UpdateAddOnRequest represents a request to update an add-on
type UpdateAlertConfigRequest ¶
type UpdateAlertConfigRequest struct {
IsEnabled *bool `json:"isEnabled"`
ThresholdPercent *float64 `json:"thresholdPercent"`
DaysBeforeEnd *int `json:"daysBeforeEnd"`
Channels []AlertChannel `json:"channels"`
Recipients []string `json:"recipients"`
WebhookURL *string `json:"webhookUrl"`
SlackChannel *string `json:"slackChannel"`
MinInterval *int `json:"minInterval"`
MaxAlertsPerDay *int `json:"maxAlertsPerDay"`
}
UpdateAlertConfigRequest is used to update an alert configuration
type UpdateCouponRequest ¶
type UpdateCouponRequest struct {
Name *string `json:"name"`
Description *string `json:"description"`
MaxRedemptions *int `json:"maxRedemptions"`
MaxRedemptionsPerOrg *int `json:"maxRedemptionsPerOrg"`
ApplicablePlans []string `json:"applicablePlans"`
ApplicableAddOns []string `json:"applicableAddOns"`
ValidUntil *time.Time `json:"validUntil"`
Status *CouponStatus `json:"status"`
Metadata map[string]interface{} `json:"metadata"`
}
UpdateCouponRequest is used to update a coupon
type UpdateCustomerRequest ¶
type UpdateCustomerRequest struct {
Email *string `json:"email,omitempty" validate:"omitempty,email"`
Name *string `json:"name,omitempty"`
Phone *string `json:"phone,omitempty"`
TaxID *string `json:"taxId,omitempty"`
TaxExempt *bool `json:"taxExempt,omitempty"`
BillingAddress *BillingAddress `json:"billingAddress,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
UpdateCustomerRequest represents a request to update a customer
type UpdateExchangeRateRequest ¶
type UpdateExchangeRateRequest struct {
Rate *float64 `json:"rate"`
ValidUntil *time.Time `json:"validUntil"`
}
UpdateExchangeRateRequest is used to update an exchange rate
type UpdateFeatureRequest ¶
type UpdateFeatureRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
Unit *string `json:"unit,omitempty" validate:"omitempty,max=50"`
ResetPeriod *ResetPeriod `json:"resetPeriod,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
DisplayOrder *int `json:"displayOrder,omitempty"`
Icon *string `json:"icon,omitempty" validate:"omitempty,max=100"`
Metadata map[string]any `json:"metadata,omitempty"`
Tiers []FeatureTier `json:"tiers,omitempty"`
}
UpdateFeatureRequest represents a request to update an existing feature
type UpdateLinkRequest ¶
type UpdateLinkRequest struct {
Value *string `json:"value,omitempty"`
IsBlocked *bool `json:"isBlocked,omitempty"`
IsHighlighted *bool `json:"isHighlighted,omitempty"`
OverrideSettings map[string]any `json:"overrideSettings,omitempty"`
}
UpdateLinkRequest represents a request to update a feature-plan link
type UpdatePlanRequest ¶
type UpdatePlanRequest struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
Description *string `json:"description,omitempty" validate:"omitempty,max=1000"`
BasePrice *int64 `json:"basePrice,omitempty" validate:"omitempty,min=0"`
TrialDays *int `json:"trialDays,omitempty" validate:"omitempty,min=0,max=365"`
Features []PlanFeature `json:"features,omitempty"`
PriceTiers []PriceTier `json:"priceTiers,omitempty"`
TierMode *TierMode `json:"tierMode,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
IsActive *bool `json:"isActive,omitempty"`
IsPublic *bool `json:"isPublic,omitempty"`
DisplayOrder *int `json:"displayOrder,omitempty"`
}
UpdatePlanRequest represents a request to update an existing plan
type UpdateSubscriptionRequest ¶
type UpdateSubscriptionRequest struct {
PlanID *xid.ID `json:"planId,omitempty"`
Quantity *int `json:"quantity,omitempty" validate:"omitempty,min=1"`
Metadata map[string]any `json:"metadata,omitempty"`
}
UpdateSubscriptionRequest represents a request to update a subscription
type UpdateTaxRateRequest ¶
type UpdateTaxRateRequest struct {
Name *string `json:"name"`
Description *string `json:"description"`
Percentage *float64 `json:"percentage"`
Behavior *TaxBehavior `json:"behavior"`
IsDefault *bool `json:"isDefault"`
IsActive *bool `json:"isActive"`
ValidUntil *time.Time `json:"validUntil"`
}
UpdateTaxRateRequest is used to update a tax rate
type UsageAction ¶
type UsageAction string
UsageAction defines the type of usage update
const ( // UsageActionSet sets the usage to an absolute value UsageActionSet UsageAction = "set" // UsageActionIncrement adds to the current usage UsageActionIncrement UsageAction = "increment" // UsageActionDecrement subtracts from the current usage UsageActionDecrement UsageAction = "decrement" )
func (UsageAction) IsValid ¶
func (u UsageAction) IsValid() bool
IsValid checks if the usage action is valid
func (UsageAction) String ¶
func (u UsageAction) String() string
String returns the string representation of usage action
type UsageLimit ¶
type UsageLimit struct {
MetricKey string `json:"metricKey"`
CurrentUsage int64 `json:"currentUsage"`
Limit int64 `json:"limit"` // -1 for unlimited
RemainingUsage int64 `json:"remainingUsage"` // -1 for unlimited
IsExceeded bool `json:"isExceeded"`
PercentUsed float64 `json:"percentUsed"`
}
UsageLimit tracks current usage against limits
func NewUsageLimit ¶
func NewUsageLimit(metricKey string, current, limit int64) *UsageLimit
NewUsageLimit creates a UsageLimit with calculated values
type UsageMetric ¶
type UsageMetric struct {
Key string `json:"key"` // Metric identifier
Name string `json:"name"` // Display name
Description string `json:"description"` // Description
Unit string `json:"unit"` // Unit of measurement (e.g., "calls", "GB")
AggregateType string `json:"aggregateType"` // "sum", "max", "last_during_period"
}
UsageMetric defines a usage metric for metered billing
type UsageRecord ¶
type UsageRecord struct {
ID xid.ID `json:"id"`
SubscriptionID xid.ID `json:"subscriptionId"` // Related subscription
OrganizationID xid.ID `json:"organizationId"` // Organization for quick queries
MetricKey string `json:"metricKey"` // Usage metric identifier (e.g., "api_calls", "storage_gb")
Quantity int64 `json:"quantity"` // Usage amount
Action UsageAction `json:"action"` // set, increment, decrement
Timestamp time.Time `json:"timestamp"` // When the usage occurred
IdempotencyKey string `json:"idempotencyKey"` // For deduplication
Metadata map[string]any `json:"metadata"` // Additional context
ProviderRecordID string `json:"providerRecordId"` // Stripe Usage Record ID
Reported bool `json:"reported"` // Has been reported to provider
ReportedAt *time.Time `json:"reportedAt"` // When reported to provider
CreatedAt time.Time `json:"createdAt"`
}
UsageRecord represents a metered usage record
func NewUsageRecord ¶
func NewUsageRecord(subID, orgID xid.ID, metricKey string, quantity int64, action UsageAction) *UsageRecord
NewUsageRecord creates a new UsageRecord
type UsageSnapshot ¶
type UsageSnapshot struct {
MetricKey string `json:"metricKey"`
CurrentValue int64 `json:"currentValue"`
Limit int64 `json:"limit"`
PercentUsed float64 `json:"percentUsed"`
Timestamp time.Time `json:"timestamp"`
}
UsageSnapshot represents a point-in-time usage snapshot
type UsageSummary ¶
type UsageSummary struct {
MetricKey string `json:"metricKey"`
TotalQuantity int64 `json:"totalQuantity"`
PeriodStart time.Time `json:"periodStart"`
PeriodEnd time.Time `json:"periodEnd"`
RecordCount int64 `json:"recordCount"`
FirstRecordAt time.Time `json:"firstRecordAt"`
LastRecordAt time.Time `json:"lastRecordAt"`
}
UsageSummary provides aggregated usage data for a metric
type VATValidationResult ¶
type VATValidationResult struct {
Valid bool `json:"valid"`
CountryCode string `json:"countryCode"`
VATNumber string `json:"vatNumber"`
Name string `json:"name"`
Address string `json:"address"`
Message string `json:"message"`
}
VATValidationResult represents the result of VAT validation
type ValidateCouponRequest ¶
type ValidateCouponRequest struct {
Code string `json:"code" validate:"required"`
OrganizationID xid.ID `json:"organizationId" validate:"required"`
PlanSlug string `json:"planSlug"`
AddOnSlug string `json:"addOnSlug"`
PurchaseAmount int64 `json:"purchaseAmount"`
}
ValidateCouponRequest is used to validate a coupon code
type ValidateCouponResponse ¶
type ValidateCouponResponse struct {
Valid bool `json:"valid"`
Coupon *Coupon `json:"coupon,omitempty"`
DiscountAmount int64 `json:"discountAmount"`
DiscountPercent float64 `json:"discountPercent"`
Message string `json:"message"`
Errors []string `json:"errors,omitempty"`
}
ValidateCouponResponse contains coupon validation result