| package usagebased |
|
|
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "time" |
|
|
| "github.com/alpacahq/alpacadecimal" |
|
|
| "github.com/openmeterio/openmeter/openmeter/billing/charges/lineage" |
| "github.com/openmeterio/openmeter/openmeter/billing/charges/models/creditrealization" |
| "github.com/openmeterio/openmeter/openmeter/billing/charges/models/ledgertransaction" |
| "github.com/openmeterio/openmeter/pkg/currencyx" |
| "github.com/openmeterio/openmeter/pkg/models" |
| "github.com/openmeterio/openmeter/pkg/timeutil" |
| ) |
|
|
| type CreditsOnlyUsageAccruedInput struct { |
| Charge Charge `json:"charge"` |
| Run RealizationRun `json:"run"` |
| BookedAt time.Time `json:"bookedAt"` |
| AmountToAllocate alpacadecimal.Decimal `json:"amountToAllocate"` |
| } |
|
|
| func (i CreditsOnlyUsageAccruedInput) Validate() error { |
| var errs []error |
|
|
| if err := i.Charge.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("charge: %w", err)) |
| } |
|
|
| if err := i.Run.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("run: %w", err)) |
| } |
|
|
| if i.BookedAt.IsZero() { |
| errs = append(errs, fmt.Errorf("booked at is required")) |
| } |
|
|
| if !i.AmountToAllocate.IsPositive() { |
| errs = append(errs, fmt.Errorf("amount to allocate must be positive")) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| type CreditsOnlyUsageAccruedCorrectionInput struct { |
| Charge Charge `json:"charge"` |
| Run RealizationRun `json:"run"` |
| BookedAt time.Time `json:"bookedAt"` |
|
|
| Corrections creditrealization.CorrectionRequest `json:"corrections"` |
| LineageSegmentsByRealization lineage.ActiveSegmentsByRealizationID `json:"-"` |
| } |
|
|
| func (i CreditsOnlyUsageAccruedCorrectionInput) Validate() error { |
| var errs []error |
|
|
| if err := i.Charge.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("charge: %w", err)) |
| } |
|
|
| if err := i.Run.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("run: %w", err)) |
| } |
|
|
| if i.BookedAt.IsZero() { |
| errs = append(errs, fmt.Errorf("booked at is required")) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| func (i CreditsOnlyUsageAccruedCorrectionInput) ValidateWith(currency currencyx.Currency) error { |
| var errs []error |
|
|
| if err := i.Validate(); err != nil { |
| return err |
| } |
|
|
| if currency == nil { |
| errs = append(errs, fmt.Errorf("currency is required")) |
| } |
|
|
| if currency != nil { |
| if err := i.Corrections.ValidateWith(currency); err != nil { |
| errs = append(errs, fmt.Errorf("corrections: %w", err)) |
| } |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| type OnInvoiceUsageAccruedInput struct { |
| Charge Charge `json:"charge"` |
| Run RealizationRun `json:"run"` |
| ServicePeriod timeutil.ClosedPeriod `json:"servicePeriod"` |
| BookedAt time.Time `json:"bookedAt"` |
| Amount alpacadecimal.Decimal `json:"amount"` |
| } |
|
|
| func (i OnInvoiceUsageAccruedInput) Validate() error { |
| var errs []error |
|
|
| if err := i.Charge.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("charge: %w", err)) |
| } |
|
|
| if err := i.Run.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("run: %w", err)) |
| } |
|
|
| if err := i.ServicePeriod.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("service period: %w", err)) |
| } |
|
|
| if i.BookedAt.IsZero() { |
| errs = append(errs, fmt.Errorf("booked at is required")) |
| } |
|
|
| if i.Amount.IsNegative() { |
| errs = append(errs, fmt.Errorf("amount cannot be negative")) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| type RunEventInput struct { |
| Charge Charge `json:"charge"` |
| Run RealizationRun `json:"run"` |
| EventAt time.Time `json:"eventAt"` |
| } |
|
|
| func (i RunEventInput) Validate() error { |
| var errs []error |
|
|
| if err := i.Charge.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("charge: %w", err)) |
| } |
|
|
| if err := i.Run.Validate(); err != nil { |
| errs = append(errs, fmt.Errorf("run: %w", err)) |
| } |
|
|
| if i.EventAt.IsZero() { |
| errs = append(errs, fmt.Errorf("event at is required")) |
| } |
|
|
| return models.NewNillableGenericValidationError(errors.Join(errs...)) |
| } |
|
|
| type ( |
| OnPaymentAuthorizedInput = RunEventInput |
| OnPaymentSettledInput = RunEventInput |
| ) |
|
|
| type Handler interface { |
| |
| OnInvoiceUsageAccrued(ctx context.Context, input OnInvoiceUsageAccruedInput) (ledgertransaction.GroupReference, error) |
|
|
| |
| OnPaymentAuthorized(ctx context.Context, input OnPaymentAuthorizedInput) (ledgertransaction.GroupReference, error) |
|
|
| |
| OnPaymentSettled(ctx context.Context, input OnPaymentSettledInput) (ledgertransaction.GroupReference, error) |
|
|
| |
| OnCreditsOnlyUsageAccrued(ctx context.Context, input CreditsOnlyUsageAccruedInput) (creditrealization.CreateAllocationInputs, error) |
|
|
| |
| OnCreditsOnlyUsageAccruedCorrection(ctx context.Context, input CreditsOnlyUsageAccruedCorrectionInput) (creditrealization.CreateCorrectionInputs, error) |
| } |
|
|
| type UnimplementedHandler struct{} |
|
|
| var _ Handler = (*UnimplementedHandler)(nil) |
|
|
| func (h UnimplementedHandler) OnInvoiceUsageAccrued(ctx context.Context, input OnInvoiceUsageAccruedInput) (ledgertransaction.GroupReference, error) { |
| return ledgertransaction.GroupReference{}, errors.New("not implemented") |
| } |
|
|
| func (h UnimplementedHandler) OnPaymentAuthorized(ctx context.Context, input OnPaymentAuthorizedInput) (ledgertransaction.GroupReference, error) { |
| return ledgertransaction.GroupReference{}, errors.New("not implemented") |
| } |
|
|
| func (h UnimplementedHandler) OnPaymentSettled(ctx context.Context, input OnPaymentSettledInput) (ledgertransaction.GroupReference, error) { |
| return ledgertransaction.GroupReference{}, errors.New("not implemented") |
| } |
|
|
| func (h UnimplementedHandler) OnCreditsOnlyUsageAccrued(ctx context.Context, input CreditsOnlyUsageAccruedInput) (creditrealization.CreateAllocationInputs, error) { |
| return nil, errors.New("not implemented") |
| } |
|
|
| func (h UnimplementedHandler) OnCreditsOnlyUsageAccruedCorrection(ctx context.Context, input CreditsOnlyUsageAccruedCorrectionInput) (creditrealization.CreateCorrectionInputs, error) { |
| return nil, errors.New("not implemented") |
| } |
|
|