| package subscription |
|
|
| import ( |
| "errors" |
| "fmt" |
| "net/http" |
| "time" |
|
|
| "github.com/openmeterio/openmeter/pkg/framework/commonhttp" |
| "github.com/openmeterio/openmeter/pkg/models" |
| ) |
|
|
| |
| |
| |
| |
|
|
| const ErrCodeSubscriptionBillingPeriodQueriedBeforeSubscriptionStart models.ErrorCode = "subscription_billing_period_queried_before_subscription_start" |
|
|
| var ErrSubscriptionBillingPeriodQueriedBeforeSubscriptionStart = models.NewValidationIssue( |
| ErrCodeSubscriptionBillingPeriodQueriedBeforeSubscriptionStart, |
| "billing period queried before subscription start", |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| func NewErrSubscriptionBillingPeriodQueriedBeforeSubscriptionStart(queriedAt, subscriptionStart time.Time) error { |
| return ErrSubscriptionBillingPeriodQueriedBeforeSubscriptionStart.WithAttr("queried_at", queriedAt).WithAttr("subscription_start", subscriptionStart) |
| } |
|
|
| func IsErrSubscriptionBillingPeriodQueriedBeforeSubscriptionStart(err error) bool { |
| return IsValidationIssueWithCode(err, ErrCodeSubscriptionBillingPeriodQueriedBeforeSubscriptionStart) |
| } |
|
|
| const ErrCodeOnlySingleSubscriptionAllowed models.ErrorCode = "only_single_subscription_allowed_per_customer_at_a_time" |
|
|
| var ErrOnlySingleSubscriptionAllowed = models.NewValidationIssue( |
| ErrCodeOnlySingleSubscriptionAllowed, |
| "only single subscription is allowed per customer at a time", |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusConflict), |
| ) |
|
|
| var ErrRestoreSubscriptionNotAllowedForMultiSubscription = models.NewGenericForbiddenError(errors.New("restore subscription is not allowed for multi-subscription")) |
|
|
| const ErrCodeOnlySingleSubscriptionItemAllowedAtATime models.ErrorCode = "only_single_subscription_item_allowed_at_a_time" |
|
|
| var ErrOnlySingleSubscriptionItemAllowedAtATime = models.NewValidationIssue( |
| ErrCodeOnlySingleSubscriptionItemAllowedAtATime, |
| "for any given feature, only one subscription item with entitlements or billable prices can exist at a time", |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusConflict), |
| ) |
|
|
| |
|
|
| func IsValidationIssueWithCode(err error, code models.ErrorCode) bool { |
| issues, err := models.AsValidationIssues(err) |
| if err != nil { |
| return false |
| } |
|
|
| if len(issues) != 1 { |
| return false |
| } |
|
|
| return issues[0].Code() == code |
| } |
|
|
| func IsValidationIssueWithBoolAttr(err error, attrName string) bool { |
| issues, err := models.AsValidationIssues(err) |
| if err != nil { |
| return false |
| } |
|
|
| if len(issues) != 1 { |
| return false |
| } |
|
|
| return issues[0].Attributes()[attrName] == true |
| } |
|
|
| |
| |
| |
|
|
| |
|
|
| const ErrCodeSubscriptionBillingAnchorIsRequired models.ErrorCode = "subscription_billing_anchor_is_required" |
|
|
| var ErrSubscriptionBillingAnchorIsRequired = models.NewValidationIssue( |
| ErrCodeSubscriptionBillingAnchorIsRequired, |
| "billing anchor is required", |
| models.WithFieldString("billingAnchor"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| |
|
|
| const ErrCodeSubscriptionPhaseStartAfterIsNegative models.ErrorCode = "subscription_phase_start_after_is_negative" |
|
|
| var ErrSubscriptionPhaseStartAfterIsNegative = models.NewValidationIssue( |
| ErrCodeSubscriptionPhaseStartAfterIsNegative, |
| "subscription phase start after cannot be negative", |
| models.WithFieldString("startAfter"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionPhaseHasNoItems models.ErrorCode = "subscription_phase_has_no_items" |
|
|
| var ErrSubscriptionPhaseHasNoItems = models.NewValidationIssue( |
| ErrCodeSubscriptionPhaseHasNoItems, |
| "subscription phase must have at least one item", |
| models.WithFieldString("items"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionPhaseItemHistoryKeyMismatch models.ErrorCode = "subscription_phase_item_history_key_mismatch" |
|
|
| var ErrSubscriptionPhaseItemHistoryKeyMismatch = models.NewValidationIssue( |
| ErrCodeSubscriptionPhaseItemHistoryKeyMismatch, |
| "subscription phase item history key mismatch", |
| models.WithFieldString("itemsByKey"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionPhaseItemKeyMismatchWithPhaseKey models.ErrorCode = "subscription_phase_item_key_mismatch_with_phase_key" |
|
|
| var ErrSubscriptionPhaseItemKeyMismatchWithPhaseKey = models.NewValidationIssue( |
| ErrCodeSubscriptionPhaseItemKeyMismatchWithPhaseKey, |
| "subscription phase item key mismatch with phase key", |
| models.WithFieldString("itemKey"), |
| models.WithFieldString("phaseKey"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| |
|
|
| const ErrCodeSubscriptionItemBillingOverrideIsOnlyAllowedForBillableItems models.ErrorCode = "subscription_item_billing_override_is_only_allowed_for_billable_items" |
|
|
| var ErrSubscriptionItemBillingOverrideIsOnlyAllowedForBillableItems = models.NewValidationIssue( |
| ErrCodeSubscriptionItemBillingOverrideIsOnlyAllowedForBillableItems, |
| "billing override is only allowed for billable items", |
| models.WithFieldString("billingBehaviorOverride"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionItemActiveFromOverrideRelativeToPhaseStartIsNegative models.ErrorCode = "subscription_item_active_from_override_relative_to_phase_start_is_negative" |
|
|
| var ErrSubscriptionItemActiveFromOverrideRelativeToPhaseStartIsNegative = models.NewValidationIssue( |
| ErrCodeSubscriptionItemActiveFromOverrideRelativeToPhaseStartIsNegative, |
| "active from override relative to phase start cannot be negative", |
| models.WithFieldString("activeFromOverrideRelativeToPhaseStart"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionItemActiveToOverrideRelativeToPhaseStartIsNegative models.ErrorCode = "subscription_item_active_to_override_relative_to_phase_start_is_negative" |
|
|
| var ErrSubscriptionItemActiveToOverrideRelativeToPhaseStartIsNegative = models.NewValidationIssue( |
| ErrCodeSubscriptionItemActiveToOverrideRelativeToPhaseStartIsNegative, |
| "active to override relative to phase start cannot be negative", |
| models.WithFieldString("activeToOverrideRelativeToPhaseStart"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| const ErrCodeSubscriptionItemHistoryOverlap models.ErrorCode = "subscription_item_history_overlap" |
|
|
| var ErrSubscriptionItemHistoryOverlap = models.NewValidationIssue( |
| ErrCodeSubscriptionItemHistoryOverlap, |
| "subscription item history overlap", |
| models.WithFieldString("itemsByKey"), |
| commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest), |
| ) |
|
|
| |
| |
| |
|
|
| |
| func NewSubscriptionNotFoundError(id string) error { |
| return &SubscriptionNotFoundError{ |
| err: models.NewGenericNotFoundError( |
| fmt.Errorf("subscription %s not found", id), |
| ), |
| } |
| } |
|
|
| var _ models.GenericError = &SubscriptionNotFoundError{} |
|
|
| |
| type SubscriptionNotFoundError struct { |
| err error |
| } |
|
|
| |
| func (e *SubscriptionNotFoundError) Error() string { |
| return e.err.Error() |
| } |
|
|
| |
| func (e *SubscriptionNotFoundError) Unwrap() error { |
| return e.err |
| } |
|
|
| |
| func IsSubscriptionNotFoundError(err error) bool { |
| if err == nil { |
| return false |
| } |
|
|
| var e *SubscriptionNotFoundError |
|
|
| return errors.As(err, &e) |
| } |
|
|
| |
| func NewPhaseNotFoundError(phaseId string) error { |
| return &PhaseNotFoundError{ |
| err: models.NewGenericNotFoundError( |
| fmt.Errorf("subscription phase %s not found", phaseId), |
| ), |
| } |
| } |
|
|
| var _ models.GenericError = &PhaseNotFoundError{} |
|
|
| |
| type PhaseNotFoundError struct { |
| err error |
| } |
|
|
| |
| func (e *PhaseNotFoundError) Error() string { |
| return e.err.Error() |
| } |
|
|
| |
| func (e *PhaseNotFoundError) Unwrap() error { |
| return e.err |
| } |
|
|
| |
| func IsPhaseNotFoundError(err error) bool { |
| if err == nil { |
| return false |
| } |
|
|
| var e *PhaseNotFoundError |
|
|
| return errors.As(err, &e) |
| } |
|
|
| |
| func NewItemNotFoundError(itemId string) error { |
| return &ItemNotFoundError{ |
| err: models.NewGenericNotFoundError( |
| fmt.Errorf("subscription item %s not found", itemId), |
| ), |
| } |
| } |
|
|
| var _ models.GenericError = &ItemNotFoundError{} |
|
|
| |
| type ItemNotFoundError struct { |
| err error |
| } |
|
|
| |
| func (e *ItemNotFoundError) Error() string { |
| return e.err.Error() |
| } |
|
|
| |
| func (e *ItemNotFoundError) Unwrap() error { |
| return e.err |
| } |
|
|
| |
| func IsItemNotFoundError(err error) bool { |
| if err == nil { |
| return false |
| } |
|
|
| var e *ItemNotFoundError |
|
|
| return errors.As(err, &e) |
| } |
|
|