Download billing/lineengine/engine.go from Leon4gr45/openmeter: direct link, hf CLI and curl.
- Browser
- Download file 8.77 kB
-
https://huggingface.co/spaces/Leon4gr45/openmeter/resolve/main/billing/lineengine/engine.go
- Command line
-
hf download hf://spaces/Leon4gr45/openmeter/billing/lineengine/engine.go
-
curl -L -o engine.go https://huggingface.co/spaces/Leon4gr45/openmeter/resolve/main/billing/lineengine/engine.go
8.77 kB
| package lineengine | |
| import ( | |
| "context" | |
| "fmt" | |
| "github.com/samber/lo" | |
| "github.com/openmeterio/openmeter/openmeter/billing" | |
| "github.com/openmeterio/openmeter/openmeter/billing/rating" | |
| "github.com/openmeterio/openmeter/openmeter/productcatalog" | |
| "github.com/openmeterio/openmeter/pkg/clock" | |
| "github.com/openmeterio/openmeter/pkg/equal" | |
| "github.com/openmeterio/openmeter/pkg/slicesx" | |
| ) | |
| var ( | |
| _ billing.LineEngine = (*Engine)(nil) | |
| _ billing.LineCalculator = (*Engine)(nil) | |
| ) | |
| type Config struct { | |
| SplitLineGroupAdapter SplitLineGroupAdapter | |
| QuantitySnapshotter QuantitySnapshotter | |
| RatingService rating.Service | |
| } | |
| func (c Config) Validate() error { | |
| if c.SplitLineGroupAdapter == nil { | |
| return fmt.Errorf("split line group adapter is required") | |
| } | |
| if c.QuantitySnapshotter == nil { | |
| return fmt.Errorf("quantity snapshotter is required") | |
| } | |
| if c.RatingService == nil { | |
| return fmt.Errorf("rating service is required") | |
| } | |
| return nil | |
| } | |
| type Engine struct { | |
| adapter SplitLineGroupAdapter | |
| quantitySnapshotter QuantitySnapshotter | |
| ratingService rating.Service | |
| } | |
| func New(config Config) (*Engine, error) { | |
| if err := config.Validate(); err != nil { | |
| return nil, err | |
| } | |
| return &Engine{ | |
| adapter: config.SplitLineGroupAdapter, | |
| quantitySnapshotter: config.QuantitySnapshotter, | |
| ratingService: config.RatingService, | |
| }, nil | |
| } | |
| func (e *Engine) GetLineEngineType() billing.LineEngineType { | |
| return billing.LineEngineTypeInvoice | |
| } | |
| func (e *Engine) OnCollectionCompleted(ctx context.Context, input billing.OnCollectionCompletedInput) (billing.StandardLines, error) { | |
| if input.Invoice.ID == "" { | |
| return nil, fmt.Errorf("invoice is required") | |
| } | |
| if input.Invoice.QuantitySnapshotedAt != nil && | |
| !input.Invoice.QuantitySnapshotedAt.Before(input.Invoice.DefaultCollectionAtForStandardInvoice()) { | |
| return input.Lines, nil | |
| } | |
| if input.Invoice.QuantitySnapshotedAt == nil && | |
| input.Invoice.CollectionAt != nil && | |
| clock.Now().Before(*input.Invoice.CollectionAt) { | |
| return input.Lines, nil | |
| } | |
| if err := e.quantitySnapshotter.SnapshotLineQuantities(ctx, input.Invoice, input.Lines); err != nil { | |
| if _, isInvalidDatabaseState := lo.ErrorsAs[*billing.ErrSnapshotInvalidDatabaseState](err); isInvalidDatabaseState { | |
| return nil, billing.ValidationIssue{ | |
| Severity: billing.ValidationIssueSeverityCritical, | |
| Code: billing.ErrInvoiceLineSnapshotFailed.Code, | |
| Message: err.Error(), | |
| Component: billing.ValidationComponentOpenMeterMetering, | |
| } | |
| } | |
| return nil, fmt.Errorf("snapshotting lines: %w", err) | |
| } | |
| return input.Lines, nil | |
| } | |
| func (e *Engine) ValidateMutableInvoiceLineEditViaAPI(_ context.Context, input billing.OnMutableInvoiceUpdateInput) error { | |
| if err := input.Validate(); err != nil { | |
| return fmt.Errorf("validating input: %w", err) | |
| } | |
| for _, override := range input.Updated { | |
| if err := validateLegacyLineOverride(override); err != nil { | |
| return err | |
| } | |
| } | |
| return nil | |
| } | |
| func (e *Engine) OnMutableInvoiceLinesEditedViaAPI(ctx context.Context, input billing.OnMutableInvoiceUpdateInput) (billing.OnMutableInvoiceUpdateResult, error) { | |
| if err := input.Validate(); err != nil { | |
| return billing.OnMutableInvoiceUpdateResult{}, fmt.Errorf("validating input: %w", err) | |
| } | |
| createdLines, err := slicesx.MapWithErr(input.Created, func(line billing.GenericInvoiceLine) (billing.GenericInvoiceLine, error) { | |
| lineID := line.GetID() | |
| line, err := e.snapshotManualStandardLineOverrideIfNeeded(ctx, input.Invoice, line) | |
| if err != nil { | |
| return nil, fmt.Errorf("snapshotting line[%s]: %w", lineID, err) | |
| } | |
| return line, nil | |
| }) | |
| if err != nil { | |
| return billing.OnMutableInvoiceUpdateResult{}, fmt.Errorf("snapshotting created lines: %w", err) | |
| } | |
| updatedLines, err := slicesx.MapWithErr(input.Updated, func(override billing.InvoiceLineOverride) (billing.GenericInvoiceLine, error) { | |
| if err := validateLegacyLineOverride(override); err != nil { | |
| return nil, err | |
| } | |
| line, err := override.ChangesToApply.Apply(override.ExistingLine) | |
| if err != nil { | |
| return nil, fmt.Errorf("applying changes to line[%s]: %w", override.ExistingLine.GetID(), err) | |
| } | |
| line, err = e.snapshotManualStandardLineOverrideIfNeeded(ctx, input.Invoice, line) | |
| if err != nil { | |
| return nil, fmt.Errorf("snapshotting line[%s]: %w", override.ExistingLine.GetID(), err) | |
| } | |
| return line, nil | |
| }) | |
| if err != nil { | |
| return billing.OnMutableInvoiceUpdateResult{}, fmt.Errorf("snapshotting updated lines: %w", err) | |
| } | |
| return billing.OnMutableInvoiceUpdateResult{ | |
| CreatedLines: createdLines, | |
| UpdatedLines: updatedLines, | |
| }, nil | |
| } | |
| func (e *Engine) snapshotManualStandardLineOverrideIfNeeded(ctx context.Context, invoice billing.GenericInvoiceReader, line billing.GenericInvoiceLine) (billing.GenericInvoiceLine, error) { | |
| if invoice.GetType() != billing.InvoiceTypeStandard { | |
| return line, nil | |
| } | |
| standardInvoice, err := invoice.AsInvoice().AsStandardInvoice() | |
| if err != nil { | |
| return nil, fmt.Errorf("getting standard invoice: %w", err) | |
| } | |
| if standardInvoice.Status == billing.StandardInvoiceStatusGathering { | |
| return line, nil | |
| } | |
| standardLine, err := line.AsInvoiceLine().AsStandardLine() | |
| if err != nil { | |
| return nil, fmt.Errorf("getting standard line: %w", err) | |
| } | |
| if err := e.quantitySnapshotter.SnapshotLineQuantities(ctx, standardInvoice, billing.StandardLines{&standardLine}); err != nil { | |
| return nil, fmt.Errorf("snapshotting line quantity: %w", err) | |
| } | |
| return standardLine.AsGenericLine(), nil | |
| } | |
| func validateLegacyLineOverride(override billing.InvoiceLineOverride) error { | |
| if override.ExistingLine.GetSplitLineGroupID() != nil { | |
| // Split-line children share progressive-billing state across invoices, so the | |
| // legacy line engine owns edits that would desynchronize later calculations. | |
| if period, ok := override.ChangesToApply.Period.Get(); ok && !period.Equal(override.ExistingLine.GetServicePeriod()) { | |
| return billing.ValidationError{ | |
| Err: fmt.Errorf("line[%s]: %w", override.ExistingLine.GetID(), billing.ErrInvoiceLineNoPeriodChangeForSplitLine), | |
| } | |
| } | |
| if price, ok := override.ChangesToApply.Price.Get(); ok && !price.Equal(override.ExistingLine.GetPrice()) { | |
| return billing.ValidationError{ | |
| Err: fmt.Errorf("line[%s]: %w", override.ExistingLine.GetID(), billing.ErrInvoiceProgressiveBillingNotSupported), | |
| } | |
| } | |
| if featureKey, ok := override.ChangesToApply.FeatureKey.Get(); ok && featureKey != override.ExistingLine.GetFeatureKey() { | |
| return billing.ValidationError{ | |
| Err: fmt.Errorf("line[%s]: %w", override.ExistingLine.GetID(), billing.ErrInvoiceProgressiveBillingNotSupported), | |
| } | |
| } | |
| // Usage-discount quantities are consumed by earlier partial invoices. Updating | |
| // the discount without a shared discount pool could make already-used quantity | |
| // exceed the new allowed quantity. | |
| if discounts, ok := override.ChangesToApply.Discounts.Get(); ok && !equal.PtrEqual(discounts.Usage, override.ExistingLine.GetRateCardDiscounts().Usage) { | |
| return billing.ValidationError{ | |
| Err: fmt.Errorf("line[%s]: %w", override.ExistingLine.GetID(), billing.ErrInvoiceLineProgressiveBillingUsageDiscountUpdateForbidden), | |
| } | |
| } | |
| } | |
| if override.ExistingLine.GetSubscriptionReference() != nil && !isFlatFeeLineOverride(override) { | |
| if period, ok := override.ChangesToApply.Period.Get(); ok && !period.Equal(override.ExistingLine.GetServicePeriod()) { | |
| return billing.ValidationError{ | |
| Err: fmt.Errorf("line[%s]: %w", override.ExistingLine.GetID(), billing.ErrInvoiceLineNoPeriodChangeForSubscriptionManagedLine), | |
| } | |
| } | |
| } | |
| return nil | |
| } | |
| func isFlatFeeLineOverride(override billing.InvoiceLineOverride) bool { | |
| existingPrice := override.ExistingLine.GetPrice() | |
| if existingPrice == nil || existingPrice.Type() != productcatalog.FlatPriceType { | |
| return false | |
| } | |
| if price, ok := override.ChangesToApply.Price.Get(); ok { | |
| return price != nil && price.Type() == productcatalog.FlatPriceType | |
| } | |
| return true | |
| } | |
| func (e *Engine) OnMutableStandardLinesDeletedBySystem(_ context.Context, _ billing.OnMutableStandardLinesDeletedInput) error { | |
| return nil | |
| } | |
| func (e *Engine) OnUnsupportedCreditNote(_ context.Context, _ billing.OnUnsupportedCreditNoteInput) error { | |
| return nil | |
| } | |
| func (e *Engine) OnStandardInvoiceCreated(_ context.Context, input billing.OnStandardInvoiceCreatedInput) (billing.StandardLines, error) { | |
| return input.Lines, nil | |
| } | |
| func (e *Engine) OnInvoiceIssued(_ context.Context, _ billing.OnInvoiceIssuedInput) error { | |
| return nil | |
| } | |
| func (e *Engine) OnPaymentAuthorized(_ context.Context, _ billing.OnPaymentAuthorizedInput) error { | |
| return nil | |
| } | |
| func (e *Engine) OnPaymentSettled(_ context.Context, _ billing.OnPaymentSettledInput) error { | |
| return nil | |
| } | |