62 строки
3.2 KiB
Go
62 строки
3.2 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gorm.io/datatypes"
|
|
|
|
"rsgit.ru/rsmon/rsmon/app/models/concerns"
|
|
)
|
|
|
|
const (
|
|
SubscriptionStatusTrialing = "trialing"
|
|
SubscriptionStatusActive = "active"
|
|
SubscriptionStatusPastDue = "past_due"
|
|
SubscriptionStatusPaused = "paused"
|
|
SubscriptionStatusCanceled = "canceled"
|
|
SubscriptionStatusExpired = "expired"
|
|
)
|
|
|
|
// Subscription is the current billable entitlement for one account. M0 only
|
|
// writes manual subscriptions; provider flows are deliberately deferred.
|
|
type Subscription struct {
|
|
concerns.Model
|
|
AccountID int64 `gorm:"not null;index" json:"account_id"`
|
|
Account *Account `json:"-"`
|
|
PlanID int64 `gorm:"not null;index" json:"plan_id"`
|
|
Plan *Plan `json:"plan,omitempty"`
|
|
Provider string `gorm:"size:16;not null;default:'manual'" json:"provider"`
|
|
ProviderSubscriptionID *string `gorm:"size:128" json:"provider_subscription_id,omitempty"`
|
|
ProviderCustomerID *string `gorm:"size:128" json:"provider_customer_id,omitempty"`
|
|
Status string `gorm:"size:24;not null;default:'active';index" json:"status"`
|
|
BillingCycle string `gorm:"size:8;not null;default:'monthly'" json:"billing_cycle"`
|
|
CurrentPeriodStart *time.Time `json:"current_period_start,omitempty"`
|
|
CurrentPeriodEnd *time.Time `gorm:"index" json:"current_period_end,omitempty"`
|
|
TrialEndsAt *time.Time `json:"trial_ends_at,omitempty"`
|
|
CancelAtPeriodEnd bool `gorm:"not null;default:false" json:"cancel_at_period_end"`
|
|
CanceledAt *time.Time `json:"canceled_at,omitempty"`
|
|
Currency string `gorm:"size:3;not null" json:"currency"`
|
|
AmountMinor int64 `gorm:"not null;default:0" json:"amount_minor"`
|
|
MetadataJSON datatypes.JSON `gorm:"type:jsonb;not null;default:'{}'" json:"metadata_json"`
|
|
concerns.Timestamped
|
|
}
|
|
|
|
// SubscriptionEvent is an append-only audit record for entitlement changes
|
|
// and provider deliveries. ProviderEventID makes future webhook processing
|
|
// idempotent without coupling the ledger to a specific PSP.
|
|
type SubscriptionEvent struct {
|
|
concerns.Model
|
|
SubscriptionID int64 `gorm:"not null;index" json:"subscription_id"`
|
|
AccountID int64 `gorm:"not null;index" json:"account_id"`
|
|
Provider string `gorm:"size:16;not null;default:'manual';uniqueIndex:idx_subscription_events_provider_event,priority:1" json:"provider"`
|
|
Kind string `gorm:"size:32;not null" json:"kind"`
|
|
FromPlanID *int64 `json:"from_plan_id,omitempty"`
|
|
ToPlanID *int64 `json:"to_plan_id,omitempty"`
|
|
AmountMinor *int64 `json:"amount_minor,omitempty"`
|
|
Currency string `gorm:"size:3" json:"currency,omitempty"`
|
|
ActorUserID *int64 `json:"actor_user_id,omitempty"`
|
|
ProviderEventID *string `gorm:"size:128;uniqueIndex:idx_subscription_events_provider_event,priority:2" json:"provider_event_id,omitempty"`
|
|
PayloadJSON datatypes.JSON `gorm:"type:jsonb;not null;default:'{}'" json:"payload_json"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|