package subscription import ( "time" "github.com/google/uuid" "gorm.io/gorm" ) // PlanName represents a subscription plan type type PlanName string const ( PlanFree PlanName = "free" PlanCreator PlanName = "creator" PlanPremium PlanName = "premium" ) // SubscriptionStatus represents the status of a user subscription type SubscriptionStatus string const ( StatusActive SubscriptionStatus = "active" StatusTrialing SubscriptionStatus = "trialing" StatusCanceled SubscriptionStatus = "canceled" StatusPastDue SubscriptionStatus = "past_due" StatusExpired SubscriptionStatus = "expired" ) // BillingCycle represents the billing frequency type BillingCycle string const ( BillingMonthly BillingCycle = "monthly" BillingYearly BillingCycle = "yearly" ) // InvoiceStatus represents the status of an invoice type InvoiceStatus string const ( InvoicePending InvoiceStatus = "pending" InvoicePaid InvoiceStatus = "paid" InvoiceFailed InvoiceStatus = "failed" InvoiceRefunded InvoiceStatus = "refunded" ) // Plan represents a subscription plan definition type Plan struct { ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"` Name PlanName `gorm:"not null;uniqueIndex;size:50" json:"name"` DisplayName string `gorm:"not null;size:100" json:"display_name"` Description string `gorm:"type:text" json:"description"` PriceMonthly int `gorm:"column:price_monthly_cents;not null;default:0" json:"price_monthly_cents"` PriceYearly int `gorm:"column:price_yearly_cents;not null;default:0" json:"price_yearly_cents"` Currency string `gorm:"size:3;default:'USD'" json:"currency"` UploadLimitMonthly *int `gorm:"column:upload_limit_monthly" json:"upload_limit_monthly"` StorageLimitBytes int64 `gorm:"not null;default:0" json:"storage_limit_bytes"` MarketplaceCommission float64 `gorm:"column:marketplace_commission_rate;type:numeric(5,4);default:0" json:"marketplace_commission_rate"` CanSellOnMarketplace bool `gorm:"not null;default:false" json:"can_sell_on_marketplace"` HasPrioritySupport bool `gorm:"not null;default:false" json:"has_priority_support"` HasCollaborationTools bool `gorm:"not null;default:false" json:"has_collaboration_tools"` HasDistribution bool `gorm:"not null;default:false" json:"has_distribution"` TrialDays int `gorm:"not null;default:0" json:"trial_days"` IsActive bool `gorm:"not null;default:true" json:"is_active"` SortOrder int `gorm:"not null;default:0" json:"sort_order"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` } func (Plan) TableName() string { return "subscription_plans" } func (p *Plan) BeforeCreate(tx *gorm.DB) error { if p.ID == uuid.Nil { p.ID = uuid.New() } return nil } // UserSubscription represents a user's active or past subscription type UserSubscription struct { ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"` UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id"` PlanID uuid.UUID `gorm:"type:uuid;not null" json:"plan_id"` Status SubscriptionStatus `gorm:"not null;size:30;default:'active'" json:"status"` BillingCycle BillingCycle `gorm:"not null;size:10;default:'monthly'" json:"billing_cycle"` CurrentPeriodStart time.Time `gorm:"not null" json:"current_period_start"` CurrentPeriodEnd time.Time `gorm:"not null" json:"current_period_end"` TrialStart *time.Time `json:"trial_start,omitempty"` TrialEnd *time.Time `json:"trial_end,omitempty"` CanceledAt *time.Time `json:"canceled_at,omitempty"` CancelAtPeriodEnd bool `gorm:"not null;default:false" json:"cancel_at_period_end"` HyperswitchSubscriptionID string `gorm:"size:255" json:"hyperswitch_subscription_id,omitempty"` HyperswitchCustomerID string `gorm:"size:255" json:"hyperswitch_customer_id,omitempty"` PaymentMethodID string `gorm:"size:255" json:"payment_method_id,omitempty"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` // Relations (loaded via Preload) Plan Plan `gorm:"foreignKey:PlanID" json:"plan,omitempty"` } func (UserSubscription) TableName() string { return "user_subscriptions" } func (s *UserSubscription) BeforeCreate(tx *gorm.DB) error { if s.ID == uuid.Nil { s.ID = uuid.New() } return nil } // IsTrialing returns true if the subscription is in trial period func (s *UserSubscription) IsTrialing() bool { return s.Status == StatusTrialing && s.TrialEnd != nil && time.Now().Before(*s.TrialEnd) } // IsActiveOrTrialing returns true if the subscription grants access func (s *UserSubscription) IsActiveOrTrialing() bool { return s.Status == StatusActive || s.Status == StatusTrialing } // Invoice represents a subscription billing invoice type Invoice struct { ID uuid.UUID `gorm:"type:uuid;primaryKey" json:"id"` SubscriptionID uuid.UUID `gorm:"type:uuid;not null" json:"subscription_id"` UserID uuid.UUID `gorm:"type:uuid;not null" json:"user_id"` AmountCents int `gorm:"not null" json:"amount_cents"` Currency string `gorm:"size:3;default:'USD'" json:"currency"` Status InvoiceStatus `gorm:"not null;size:30;default:'pending'" json:"status"` BillingPeriodStart time.Time `gorm:"not null" json:"billing_period_start"` BillingPeriodEnd time.Time `gorm:"not null" json:"billing_period_end"` HyperswitchPaymentID string `gorm:"size:255" json:"hyperswitch_payment_id,omitempty"` PaidAt *time.Time `json:"paid_at,omitempty"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` } func (Invoice) TableName() string { return "subscription_invoices" } func (i *Invoice) BeforeCreate(tx *gorm.DB) error { if i.ID == uuid.Nil { i.ID = uuid.New() } return nil }