| package subscription |
|
|
| import ( |
| "context" |
| "fmt" |
|
|
| "github.com/openmeterio/openmeter/openmeter/app" |
| "github.com/openmeterio/openmeter/openmeter/billing" |
| customerbilling "github.com/openmeterio/openmeter/openmeter/billing/validators/customerbilling" |
| "github.com/openmeterio/openmeter/openmeter/customer" |
| "github.com/openmeterio/openmeter/openmeter/subscription" |
| "github.com/openmeterio/openmeter/pkg/models" |
| ) |
|
|
| type Validator struct { |
| subscription.NoOpSubscriptionCommandHook |
| billingService billing.Service |
| } |
|
|
| func NewValidator(billingService billing.Service) (subscription.SubscriptionCommandHook, error) { |
| if billingService == nil { |
| return nil, fmt.Errorf("billing service is required") |
| } |
|
|
| return &Validator{ |
| billingService: billingService, |
| }, nil |
| } |
|
|
| func (v Validator) AfterCreate(ctx context.Context, view subscription.SubscriptionView) error { |
| err := v.validateBillingSetup(ctx, view) |
| if err != nil { |
| return models.NewGenericConflictError(fmt.Errorf("invalid billing setup: %w", err)) |
| } |
|
|
| return nil |
| } |
|
|
| func (v Validator) AfterUpdate(ctx context.Context, view subscription.SubscriptionView) error { |
| err := v.validateBillingSetup(ctx, view) |
| if err != nil { |
| return models.NewGenericConflictError(fmt.Errorf("invalid billing setup: %w", err)) |
| } |
|
|
| return nil |
| } |
|
|
| func (v Validator) validateBillingSetup(ctx context.Context, view subscription.SubscriptionView) error { |
| |
| |
|
|
| if !v.hasBillableItems(view) { |
| return nil |
| } |
|
|
| return customerbilling.ValidateCustomerInvoicingApp( |
| ctx, |
| v.billingService, |
| customer.CustomerID{ |
| Namespace: view.Subscription.Namespace, |
| ID: view.Subscription.CustomerId, |
| }, |
| []app.CapabilityType{ |
| |
| app.CapabilityTypeCalculateTax, |
| app.CapabilityTypeInvoiceCustomers, |
| app.CapabilityTypeCollectPayments, |
| }, |
| ) |
| } |
|
|
| func (v Validator) hasBillableItems(view subscription.SubscriptionView) bool { |
| for _, phase := range view.Phases { |
| for _, items := range phase.ItemsByKey { |
| for _, item := range items { |
| if item.SubscriptionItem.RateCard.AsMeta().Price != nil { |
| return true |
| } |
| } |
| } |
| } |
|
|
| return false |
| } |
|
|