mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-06 16:16:26 +00:00
100 lines
3.5 KiB
Go
100 lines
3.5 KiB
Go
package licensing
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const DefaultTrialDuration = 14 * 24 * time.Hour
|
|
|
|
type TrialStartDenialReason string
|
|
|
|
const (
|
|
TrialStartAllowed TrialStartDenialReason = ""
|
|
TrialStartDeniedLicense TrialStartDenialReason = "license_active"
|
|
TrialStartDeniedAlreadyUsed TrialStartDenialReason = "already_used"
|
|
TrialStartDeniedSubscription TrialStartDenialReason = "subscription_active"
|
|
TrialStartDeniedMigrationPending TrialStartDenialReason = "commercial_migration_pending"
|
|
TrialStartDeniedMigrationFailed TrialStartDenialReason = "commercial_migration_failed"
|
|
)
|
|
|
|
type TrialStartDecision struct {
|
|
Allowed bool
|
|
Reason TrialStartDenialReason
|
|
}
|
|
|
|
func EvaluateTrialStartEligibility(hasActiveLicense bool, existing *BillingState) TrialStartDecision {
|
|
if hasActiveLicense {
|
|
return TrialStartDecision{Allowed: false, Reason: TrialStartDeniedLicense}
|
|
}
|
|
if existing == nil {
|
|
return TrialStartDecision{Allowed: true, Reason: TrialStartAllowed}
|
|
}
|
|
if existing.CommercialMigration != nil {
|
|
switch existing.CommercialMigration.State {
|
|
case CommercialMigrationStatePending:
|
|
return TrialStartDecision{Allowed: false, Reason: TrialStartDeniedMigrationPending}
|
|
case CommercialMigrationStateFailed:
|
|
return TrialStartDecision{Allowed: false, Reason: TrialStartDeniedMigrationFailed}
|
|
}
|
|
}
|
|
if existing.TrialStartedAt != nil {
|
|
return TrialStartDecision{Allowed: false, Reason: TrialStartDeniedAlreadyUsed}
|
|
}
|
|
switch existing.SubscriptionState {
|
|
case SubStateActive, SubStateGrace, SubStateSuspended:
|
|
return TrialStartDecision{Allowed: false, Reason: TrialStartDeniedSubscription}
|
|
default:
|
|
return TrialStartDecision{Allowed: true, Reason: TrialStartAllowed}
|
|
}
|
|
}
|
|
|
|
func TrialStartError(reason TrialStartDenialReason) (code, message string, includeOrgID bool) {
|
|
switch reason {
|
|
case TrialStartDeniedLicense:
|
|
return "trial_not_available", "Trial cannot be started while a license is active", false
|
|
case TrialStartDeniedAlreadyUsed:
|
|
return "trial_already_used", "Trial has already been used for this organization", true
|
|
case TrialStartDeniedSubscription:
|
|
return "trial_not_available", "Trial cannot be started while a subscription is active", true
|
|
case TrialStartDeniedMigrationPending:
|
|
return "trial_not_available", "Trial cannot be started while a paid v5 license migration is pending", false
|
|
case TrialStartDeniedMigrationFailed:
|
|
return "trial_not_available", "Trial cannot be started until the paid v5 license migration is resolved", false
|
|
default:
|
|
return "", "", false
|
|
}
|
|
}
|
|
|
|
func TrialWindow(now time.Time, duration time.Duration) (startedAt, endsAt int64) {
|
|
if duration <= 0 {
|
|
duration = DefaultTrialDuration
|
|
}
|
|
startedAt = now.Unix()
|
|
endsAt = now.Add(duration).Unix()
|
|
return startedAt, endsAt
|
|
}
|
|
|
|
func BuildTrialBillingState(now time.Time, capabilities []string) *BillingState {
|
|
return BuildTrialBillingStateWithPlan(now, capabilities, string(SubStateTrial), DefaultTrialDuration)
|
|
}
|
|
|
|
func BuildTrialBillingStateWithPlan(now time.Time, capabilities []string, planVersion string, duration time.Duration) *BillingState {
|
|
startedAt, endsAt := TrialWindow(now, duration)
|
|
planVersion = strings.TrimSpace(planVersion)
|
|
if planVersion == "" {
|
|
planVersion = string(SubStateTrial)
|
|
}
|
|
|
|
state := &BillingState{
|
|
Capabilities: append([]string(nil), capabilities...),
|
|
Limits: map[string]int64{},
|
|
MetersEnabled: []string{},
|
|
PlanVersion: planVersion,
|
|
SubscriptionState: SubStateTrial,
|
|
TrialStartedAt: &startedAt,
|
|
TrialEndsAt: &endsAt,
|
|
}
|
|
state.GrantQuickstartCredits()
|
|
return state
|
|
}
|