usagebased

package
v1.0.0-beta.228 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: Apache-2.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const ErrCodeActiveRealizationRunAlreadyExists models.ErrorCode = "active_realization_run_already_exists"
View Source
const ErrCodeChargeTotalIsNegative models.ErrorCode = "charge_total_is_negative"
View Source
const ErrCodeCreditAllocationsDoNotMatchTotal models.ErrorCode = "credit_allocations_do_not_match_total"
View Source
const (
	InternalCollectionPeriod time.Duration = time.Minute
)

Variables

View Source
var ErrActiveRealizationRunAlreadyExists = models.NewValidationIssue(
	ErrCodeActiveRealizationRunAlreadyExists,
	"an active realization run already exists for this charge, please finalize any draft invoices for the customer first",
	models.WithCriticalSeverity(),
	commonhttp.WithHTTPStatusCodeAttribute(http.StatusBadRequest),
)

Functions

func IsMutableFinalRealizationStatus

func IsMutableFinalRealizationStatus(status Status) bool

func IsMutableInvoiceBackedRealizationStatus

func IsMutableInvoiceBackedRealizationStatus(status Status) bool

Types

type AdvanceChargeInput

type AdvanceChargeInput struct {
	ChargeID         meta.ChargeID
	CustomerOverride billing.CustomerOverrideWithDetails
	FeatureMeters    feature.FeatureMeters
}

func (AdvanceChargeInput) Validate

func (i AdvanceChargeInput) Validate() error

type BillingMeteredQuantity

type BillingMeteredQuantity struct {
	// PreLinePeriod is the cumulative quantity already represented by earlier
	// billed runs.
	PreLinePeriod alpacadecimal.Decimal
	// LinePeriod is the quantity represented by the current standard invoice
	// line.
	LinePeriod alpacadecimal.Decimal
}

BillingMeteredQuantity maps a cumulative charge run quantity to the quantity semantics expected by billing.StandardLine. RealizationRun.MeteredQuantity is cumulative from the charge service-period start to the run's ServicePeriodTo, while standard invoice lines need the current line-period quantity plus the quantity already represented by earlier billed lines.

type Charge

type Charge struct {
	ChargeBase

	Realizations RealizationRuns `json:"realizations"`
	Expands      Expands         `json:"expands"`
}

func (Charge) GetBase

func (c Charge) GetBase() ChargeBase

func (Charge) GetCurrentRealizationRun

func (c Charge) GetCurrentRealizationRun() (RealizationRun, error)

func (Charge) GetCustomerID

func (c Charge) GetCustomerID() customer.CustomerID

func (Charge) GetFeatureKeyOrID

func (c Charge) GetFeatureKeyOrID() ref.IDOrKey

func (Charge) GetStatus

func (c Charge) GetStatus() Status

func (Charge) ResolveFeatureMeter

func (c Charge) ResolveFeatureMeter(featureMeters feature.FeatureMeters) (feature.FeatureMeter, error)

func (Charge) Validate

func (c Charge) Validate() error

func (Charge) WithBase

func (c Charge) WithBase(base ChargeBase) Charge

func (Charge) WithStatus

func (c Charge) WithStatus(status Status) Charge

type ChargeAdapter

type ChargeAdapter interface {
	CreateCharges(ctx context.Context, charges CreateChargesInput) ([]Charge, error)
	UpdateCharge(ctx context.Context, charge ChargeBase) (ChargeBase, error)
	UpdateSubscriptionItemID(ctx context.Context, charge Charge, newSubscriptionItemID string) (Charge, error)
	DeleteCharge(ctx context.Context, charge Charge) error
	GetByIDs(ctx context.Context, input GetByIDsInput) ([]Charge, error)
	GetByID(ctx context.Context, input GetByIDInput) (Charge, error)
}

type ChargeBase

type ChargeBase struct {
	meta.ManagedResource

	Intent Intent `json:"intent"`
	Status Status `json:"status"`

	State State `json:"state"`
}

func (ChargeBase) ErrorAttributes

func (c ChargeBase) ErrorAttributes() models.Attributes

func (ChargeBase) GetChargeID

func (c ChargeBase) GetChargeID() meta.ChargeID

func (ChargeBase) GetCurrency

func (c ChargeBase) GetCurrency() currencyx.Code

func (ChargeBase) GetCustomerID

func (c ChargeBase) GetCustomerID() customer.CustomerID

func (ChargeBase) Validate

func (c ChargeBase) Validate() error

type ChargeWithGatheringLine

type ChargeWithGatheringLine struct {
	Charge                Charge
	GatheringLineToCreate *billing.GatheringLine
}

type Charges

type Charges []Charge

func (Charges) GetFeatureKeysOrIDs

func (c Charges) GetFeatureKeysOrIDs() []ref.IDOrKey

GetFeatureKeysOrIDs returns the unique state-aware feature references for the charges. Each charge contributes the ref returned by GetFeatureKeyOrID, so created charges use keys, deleted charges prefer IDs and fall back to keys, and all other states use IDs.

type CreateChargesInput

type CreateChargesInput struct {
	Namespace string
	Intents   []CreateIntent
}

func (CreateChargesInput) Validate

func (i CreateChargesInput) Validate() error

type CreateInput

type CreateInput struct {
	Namespace     string
	Intents       []Intent
	FeatureMeters feature.FeatureMeters
}

func (CreateInput) Validate

func (i CreateInput) Validate() error

type CreateIntent

type CreateIntent struct {
	Intent
	FeatureID    string
	RatingEngine RatingEngine
}

func (CreateIntent) Validate

func (i CreateIntent) Validate() error

type CreateRealizationRunInput

type CreateRealizationRunInput struct {
	FeatureID                 string                `json:"featureId"`
	Type                      RealizationRunType    `json:"type"`
	StoredAtLT                time.Time             `json:"storedAtLT"`
	ServicePeriodTo           time.Time             `json:"servicePeriodTo"`
	LineID                    *string               `json:"lineId,omitempty"`
	InvoiceID                 *string               `json:"invoiceId,omitempty"`
	MeteredQuantity           alpacadecimal.Decimal `json:"meteredQuantity"`
	Totals                    totals.Totals         `json:"totals"`
	NoFiatTransactionRequired bool                  `json:"noFiatTransactionRequired"`
}

func (CreateRealizationRunInput) Normalized

func (CreateRealizationRunInput) Validate

func (r CreateRealizationRunInput) Validate() error

type CreditsOnlyUsageAccruedCorrectionInput

type CreditsOnlyUsageAccruedCorrectionInput struct {
	Charge     Charge         `json:"charge"`
	Run        RealizationRun `json:"run"`
	AllocateAt time.Time      `json:"allocateAt"`

	Corrections                  creditrealization.CorrectionRequest   `json:"corrections"`
	LineageSegmentsByRealization lineage.ActiveSegmentsByRealizationID `json:"-"`
}

type CreditsOnlyUsageAccruedInput

type CreditsOnlyUsageAccruedInput struct {
	Charge           Charge                `json:"charge"`
	Run              RealizationRun        `json:"run"`
	AllocateAt       time.Time             `json:"allocateAt"`
	AmountToAllocate alpacadecimal.Decimal `json:"amountToAllocate"`
}

func (CreditsOnlyUsageAccruedInput) Validate

func (i CreditsOnlyUsageAccruedInput) Validate() error

type DetailedLine

type DetailedLine struct {
	stddetailedline.Base

	PricerReferenceID string  `json:"pricerReferenceID"`
	CorrectsRunID     *string `json:"correctsRunID,omitempty"`
}

func (DetailedLine) Clone

func (l DetailedLine) Clone() DetailedLine

func (DetailedLine) Validate

func (l DetailedLine) Validate() error

type DetailedLines

type DetailedLines []DetailedLine

func NewDetailedLinesFromBilling

func NewDetailedLinesFromBilling(
	intent Intent,
	defaultServicePeriod timeutil.ClosedPeriod,
	lines billingrating.DetailedLines,
) DetailedLines

func (DetailedLines) Clone

func (l DetailedLines) Clone() DetailedLines

func (DetailedLines) Sort

func (l DetailedLines) Sort()

func (DetailedLines) StripServicePeriodFromUniqueReferenceID

func (l DetailedLines) StripServicePeriodFromUniqueReferenceID() (DetailedLines, error)

StripServicePeriodFromUniqueReferenceID returns cloned detailed lines where ChildUniqueReferenceID is stripped at the first service-period suffix marker.

func (DetailedLines) SumTotals

func (l DetailedLines) SumTotals() totals.Totals

func (DetailedLines) Validate

func (l DetailedLines) Validate() error

func (DetailedLines) WithServicePeriodFromUniqueReferenceID

func (l DetailedLines) WithServicePeriodFromUniqueReferenceID() (DetailedLines, error)

WithServicePeriodFromUniqueReferenceID returns cloned detailed lines where ChildUniqueReferenceID contains the line's ServicePeriod persistence suffix.

type Expands

type Expands struct {
	RealtimeUsage *totals.Totals `json:"realtimeUsage,omitempty"`
}

func (Expands) Validate

func (e Expands) Validate() error

type GetByIDInput

type GetByIDInput struct {
	ChargeID meta.ChargeID
	Expands  meta.Expands
}

func (GetByIDInput) Validate

func (i GetByIDInput) Validate() error

type GetByIDsInput

type GetByIDsInput struct {
	Namespace string
	IDs       []string
	Expands   meta.Expands
}

func (GetByIDsInput) Validate

func (i GetByIDsInput) Validate() error

type GetCurrentTotalsInput

type GetCurrentTotalsInput struct {
	ChargeID meta.ChargeID
}

func (GetCurrentTotalsInput) Validate

func (i GetCurrentTotalsInput) Validate() error

type GetCurrentTotalsResult

type GetCurrentTotalsResult struct {
	Charge    Charge
	DueTotals totals.Totals
}

type Handler

type Handler interface {
	// OnInvoiceUsageAccrued is called when invoice-settled usage-based usage is sent to the customer.
	OnInvoiceUsageAccrued(ctx context.Context, input OnInvoiceUsageAccruedInput) (ledgertransaction.GroupReference, error)

	// OnPaymentAuthorized is called when an invoice-backed usage-based run receives payment authorization.
	OnPaymentAuthorized(ctx context.Context, input OnPaymentAuthorizedInput) (ledgertransaction.GroupReference, error)

	// OnPaymentSettled is called when an invoice-backed usage-based run payment is settled.
	OnPaymentSettled(ctx context.Context, input OnPaymentSettledInput) (ledgertransaction.GroupReference, error)

	// OnCreditsOnlyUsageAccrued is called when a credit-only usage-based charge needs to be allocated as credits fully.
	OnCreditsOnlyUsageAccrued(ctx context.Context, input CreditsOnlyUsageAccruedInput) (creditrealization.CreateAllocationInputs, error)

	// OnCreditsOnlyUsageAccruedCorrection is called when a credit-only usage-based charge needs to be corrected.
	OnCreditsOnlyUsageAccruedCorrection(ctx context.Context, input CreditsOnlyUsageAccruedCorrectionInput) (creditrealization.CreateCorrectionInputs, error)
}

type Intent

type Intent struct {
	meta.Intent

	InvoiceAt      time.Time                     `json:"invoiceAt"`
	SettlementMode productcatalog.SettlementMode `json:"settlementMode"`

	FeatureKey string `json:"featureKey"`

	Price productcatalog.Price `json:"price"`

	Discounts productcatalog.Discounts `json:"discounts"`
}

func (Intent) Normalized

func (i Intent) Normalized() Intent

func (Intent) Validate

func (i Intent) Validate() error

type OnInvoiceUsageAccruedInput

type OnInvoiceUsageAccruedInput struct {
	Charge        Charge                `json:"charge"`
	Run           RealizationRun        `json:"run"`
	ServicePeriod timeutil.ClosedPeriod `json:"servicePeriod"`
	Amount        alpacadecimal.Decimal `json:"amount"`
}

func (OnInvoiceUsageAccruedInput) Validate

func (i OnInvoiceUsageAccruedInput) Validate() error

type OnPaymentAuthorizedInput

type OnPaymentAuthorizedInput = RunEventInput

type OnPaymentSettledInput

type OnPaymentSettledInput = RunEventInput

type RateableIntent

type RateableIntent struct {
	Intent

	ServicePeriod  timeutil.ClosedPeriod
	MeterValue     alpacadecimal.Decimal
	CreditsApplied billing.CreditsApplied
}

func (RateableIntent) GetCreditsApplied

func (r RateableIntent) GetCreditsApplied() billing.CreditsApplied

func (RateableIntent) GetCurrency

func (r RateableIntent) GetCurrency() currencyx.Code

func (RateableIntent) GetFeatureKey

func (r RateableIntent) GetFeatureKey() string

func (RateableIntent) GetMeteredPreLinePeriodQuantity

func (r RateableIntent) GetMeteredPreLinePeriodQuantity() (*alpacadecimal.Decimal, error)

func (RateableIntent) GetMeteredQuantity

func (r RateableIntent) GetMeteredQuantity() (*alpacadecimal.Decimal, error)

func (RateableIntent) GetName

func (r RateableIntent) GetName() string

func (RateableIntent) GetPreviouslyBilledAmount

func (r RateableIntent) GetPreviouslyBilledAmount() (alpacadecimal.Decimal, error)

func (RateableIntent) GetPrice

func (r RateableIntent) GetPrice() *productcatalog.Price

func (RateableIntent) GetProgressivelyBilledServicePeriod

func (r RateableIntent) GetProgressivelyBilledServicePeriod() (timeutil.ClosedPeriod, error)

func (RateableIntent) GetRateCardDiscounts

func (r RateableIntent) GetRateCardDiscounts() billing.Discounts

func (RateableIntent) GetServicePeriod

func (r RateableIntent) GetServicePeriod() timeutil.ClosedPeriod

func (RateableIntent) GetStandardLineDiscounts

func (r RateableIntent) GetStandardLineDiscounts() billing.StandardLineDiscounts

func (RateableIntent) IsProgressivelyBilled

func (r RateableIntent) IsProgressivelyBilled() bool

type RatingEngine

type RatingEngine string
const (
	// RatingEngineDelta rates the current cumulative meter snapshot, subtracts
	// already booked detailed lines, and books the remainder on the current run
	// service period.
	RatingEngineDelta RatingEngine = "delta"
	// RatingEnginePeriodPreserving rates cumulative snapshots per service
	// period and preserves correction lines on their original service periods.
	RatingEnginePeriodPreserving RatingEngine = "period_preserving"
)

func (RatingEngine) Validate

func (e RatingEngine) Validate() error

func (RatingEngine) Values

func (e RatingEngine) Values() []string

type RealizationRun

type RealizationRun struct {
	RealizationRunBase

	// Realizations
	CreditsAllocated creditrealization.Realizations `json:"creditsAllocated"`
	InvoiceUsage     *invoicedusage.AccruedUsage    `json:"invoicedUsage"`
	Payment          *payment.Invoiced              `json:"payment"`
	DetailedLines    mo.Option[DetailedLines]       `json:"detailedLines,omitzero"`
}

func (RealizationRun) IsVoidedBillingHistory

func (r RealizationRun) IsVoidedBillingHistory() bool

IsVoidedBillingHistory reports whether this run must be ignored as billing history. Deleted runs were already cleaned up through billing; unsupported credit-note runs are retained for audit even though the invoice line should have been removed once prorating/credit-note support exists.

func (RealizationRun) Validate

func (r RealizationRun) Validate() error

type RealizationRunAdapter

type RealizationRunAdapter interface {
	CreateRealizationRun(ctx context.Context, chargeID meta.ChargeID, input CreateRealizationRunInput) (RealizationRunBase, error)
	UpdateRealizationRun(ctx context.Context, input UpdateRealizationRunInput) (RealizationRunBase, error)
	UpsertRunDetailedLines(ctx context.Context, chargeID meta.ChargeID, runID RealizationRunID, lines DetailedLines) error
	FetchDetailedLines(ctx context.Context, charge Charge) (Charge, error)
}

type RealizationRunBase

type RealizationRunBase struct {
	ID RealizationRunID
	models.ManagedModel

	FeatureID string  `json:"featureId"`
	LineID    *string `json:"lineId,omitempty"`
	InvoiceID *string `json:"invoiceId,omitempty"`

	Type        RealizationRunType `json:"type"`
	InitialType RealizationRunType `json:"initialType"`
	StoredAtLT  time.Time          `json:"storedAtLT"`
	// ServicePeriodTo is the end of the service period for the realization run.
	ServicePeriodTo time.Time `json:"servicePeriodTo"`
	// MeteredQuantity is the metered quantity for time IN [intent.servicePeriod.from, servicePeriodTo) capped by stored_at < StoredAtLT.
	MeteredQuantity           alpacadecimal.Decimal `json:"meteredQuantity"`
	Totals                    totals.Totals         `json:"totals"`
	NoFiatTransactionRequired bool                  `json:"noFiatTransactionRequired"`
}

func (RealizationRunBase) Normalized

func (r RealizationRunBase) Normalized() RealizationRunBase

func (RealizationRunBase) Validate

func (r RealizationRunBase) Validate() error

type RealizationRunCreditAllocationAdapter

type RealizationRunCreditAllocationAdapter interface {
	CreateRunCreditRealization(ctx context.Context, runID RealizationRunID, creditAllocations creditrealization.CreateInputs) (creditrealization.Realizations, error)
}

type RealizationRunID

type RealizationRunID models.NamespacedID

func (RealizationRunID) Validate

func (i RealizationRunID) Validate() error

type RealizationRunInvoiceUsageAdapter

type RealizationRunInvoiceUsageAdapter interface {
	CreateRunInvoicedUsage(ctx context.Context, runID RealizationRunID, invoicedUsage invoicedusage.AccruedUsage) (invoicedusage.AccruedUsage, error)
}

type RealizationRunPaymentAdapter

type RealizationRunPaymentAdapter interface {
	CreateRunPayment(ctx context.Context, runID RealizationRunID, in payment.InvoicedCreate) (payment.Invoiced, error)
	UpdateRunPayment(ctx context.Context, in payment.Invoiced) (payment.Invoiced, error)
}

type RealizationRunType

type RealizationRunType string
const (
	RealizationRunTypeFinalRealization                  RealizationRunType = "final_realization"
	RealizationRunTypePartialInvoice                    RealizationRunType = "partial_invoice"
	RealizationRunTypeInvalidDueToUnsupportedCreditNote RealizationRunType = "invalid_due_to_unsupported_credit_note"
)

func (RealizationRunType) IsVoidedBillingHistory

func (t RealizationRunType) IsVoidedBillingHistory() bool

IsVoidedBillingHistory reports whether this run type is audit-only billing history that should not participate in future billing calculations.

func (RealizationRunType) Validate

func (t RealizationRunType) Validate() error

func (RealizationRunType) Values

func (t RealizationRunType) Values() []string

type RealizationRuns

type RealizationRuns []RealizationRun

func (RealizationRuns) BisectByTimestamp

func (r RealizationRuns) BisectByTimestamp(chargeIntentServicePeriod timeutil.ClosedPeriod, at time.Time) (before RealizationRuns, containingOrAfter RealizationRuns)

BisectByTimestamp splits non-voided realization runs by their derived service period relative to at.

The returned before slice contains every non-voided run whose derived service period ends at or before at. The returned containingOrAfter slice contains every non-voided run whose derived service period contains at, or whose derived service period starts after at. Each run's service-period start is derived from the previous non-voided run's ServicePeriodTo, with the first run starting at chargeIntentServicePeriod.From. Both returned slices are sorted by ServicePeriodTo and then CreatedAt.

func (RealizationRuns) GetByID

func (r RealizationRuns) GetByID(id string) (RealizationRun, error)

func (RealizationRuns) GetByLineID

func (r RealizationRuns) GetByLineID(lineID string) (RealizationRun, error)

func (RealizationRuns) MapToBillingMeteredQuantity

func (r RealizationRuns) MapToBillingMeteredQuantity(currentRun RealizationRun) (BillingMeteredQuantity, error)

func (*RealizationRuns) SetRealizationRun

func (r *RealizationRuns) SetRealizationRun(updatedRun RealizationRun) error

func (RealizationRuns) Sum

func (r RealizationRuns) Sum() totals.Totals

Sum returns the aggregate totals across non-voided billing history.

func (RealizationRuns) Validate

func (r RealizationRuns) Validate() error

func (RealizationRuns) Without

func (RealizationRuns) WithoutVoidedBillingHistory

func (r RealizationRuns) WithoutVoidedBillingHistory() RealizationRuns

WithoutVoidedBillingHistory returns runs that still represent effective invoice or ledger history.

type RunEventInput

type RunEventInput struct {
	Charge Charge         `json:"charge"`
	Run    RealizationRun `json:"run"`
}

func (RunEventInput) Validate

func (i RunEventInput) Validate() error

type Service

type Service interface {
	UsageBasedService
	GetLineEngine() billing.LineEngine
}

type State

type State struct {
	CurrentRealizationRunID *string      `json:"currentRealizationRunId"`
	AdvanceAfter            *time.Time   `json:"advanceAfter"`
	FeatureID               string       `json:"featureId"`
	RatingEngine            RatingEngine `json:"ratingEngine"`
}

func (State) Normalized

func (s State) Normalized() State

func (State) Validate

func (s State) Validate() error

type Status

type Status string
const (
	StatusCreated Status = Status(meta.ChargeStatusCreated)

	// Active status and substates
	StatusActive Status = Status(meta.ChargeStatusActive)

	StatusActivePartialInvoiceStarted                Status = "active.partial_invoice.started"
	StatusActivePartialInvoiceWaitingForCollection   Status = "active.partial_invoice.waiting_for_collection"
	StatusActivePartialInvoiceProcessing             Status = "active.partial_invoice.processing"
	StatusActivePartialInvoiceIssuing                Status = "active.partial_invoice.issuing"
	StatusActivePartialInvoiceCompleted              Status = "active.partial_invoice.completed"
	StatusActiveFinalRealizationStarted              Status = "active.final_realization.started"
	StatusActiveFinalRealizationWaitingForCollection Status = "active.final_realization.waiting_for_collection"
	StatusActiveFinalRealizationProcessing           Status = "active.final_realization.processing"
	StatusActiveFinalRealizationIssuing              Status = "active.final_realization.issuing"
	StatusActiveFinalRealizationCompleted            Status = "active.final_realization.completed"
	StatusActiveAwaitingPaymentSettlement            Status = "active.awaiting_payment_settlement"

	StatusFinal   Status = Status(meta.ChargeStatusFinal)
	StatusDeleted Status = Status(meta.ChargeStatusDeleted)
)

func (Status) ToMetaChargeStatus

func (s Status) ToMetaChargeStatus() (meta.ChargeStatus, error)

func (Status) Validate

func (s Status) Validate() error

func (Status) Values

func (Status) Values() []string

type UnimplementedHandler

type UnimplementedHandler struct{}

func (UnimplementedHandler) OnInvoiceUsageAccrued

func (UnimplementedHandler) OnPaymentAuthorized

func (UnimplementedHandler) OnPaymentSettled

type UpdateRealizationRunInput

type UpdateRealizationRunInput struct {
	ID RealizationRunID

	Type                      mo.Option[RealizationRunType]    `json:"type"`
	StoredAtLT                mo.Option[time.Time]             `json:"storedAtLT"`
	DeletedAt                 mo.Option[*time.Time]            `json:"deletedAt,omitempty"`
	LineID                    mo.Option[*string]               `json:"lineId,omitempty"`
	MeteredQuantity           mo.Option[alpacadecimal.Decimal] `json:"meteredQuantity"`
	Totals                    mo.Option[totals.Totals]         `json:"totals"`
	NoFiatTransactionRequired mo.Option[bool]                  `json:"noFiatTransactionRequired"`
}

func (UpdateRealizationRunInput) Normalized

func (UpdateRealizationRunInput) Validate

func (r UpdateRealizationRunInput) Validate() error

type UsageBasedService

type UsageBasedService interface {
	Create(ctx context.Context, input CreateInput) ([]ChargeWithGatheringLine, error)
	GetByIDs(ctx context.Context, input GetByIDsInput) ([]Charge, error)
	UpdateSubscriptionItemID(ctx context.Context, charge Charge, newSubscriptionItemID string) (Charge, error)
	AdvanceCharge(ctx context.Context, input AdvanceChargeInput) (*Charge, error)
	TriggerPatch(ctx context.Context, charge meta.ChargeID, patch meta.Patch) (meta.TriggerPatchResult[Charge], error)
	GetCurrentTotals(ctx context.Context, input GetCurrentTotalsInput) (GetCurrentTotalsResult, error)
}

Directories

Path Synopsis
run

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL