usagebased

package
v1.0.0-beta.230 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 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 IsMutableRealizationStatus

func IsMutableRealizationStatus(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)
	CreateChargeOverride(ctx context.Context, charge ChargeBase, override IntentMutableFields) (ChargeBase, error)
	DeleteChargeOverride(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 OverridableIntent `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) GetIntentDeletedAt

func (c ChargeBase) GetIntentDeletedAt() *time.Time

GetIntentDeletedAt returns the effective intent deletion timestamp. If an override is present, the override intent owns deletion; otherwise the base intent does.

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      OverridableIntent
	Annotations models.Annotations `json:"annotations"`

	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"`
	BookedAt time.Time      `json:"bookedAt"`

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

func (CreditsOnlyUsageAccruedCorrectionInput) Validate

func (CreditsOnlyUsageAccruedCorrectionInput) ValidateWith

func (i CreditsOnlyUsageAccruedCorrectionInput) ValidateWith(currencyCalculator currencyx.Calculator) error

type CreditsOnlyUsageAccruedInput

type CreditsOnlyUsageAccruedInput struct {
	Charge           Charge                `json:"charge"`
	Run              RealizationRun        `json:"run"`
	BookedAt         time.Time             `json:"bookedAt"`
	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
	IntentMutableFields `json:"intentMutableFields"`
	SettlementMode      productcatalog.SettlementMode `json:"settlementMode"`
	FeatureKey          string                        `json:"featureKey"`
}

func (Intent) AsOverridableIntent

func (i Intent) AsOverridableIntent() OverridableIntent

AsOverridableIntent maps the intent's mutable fields as the base layer.

func (Intent) Normalized

func (i Intent) Normalized() Intent

func (Intent) Validate

func (i Intent) Validate() error

type IntentMutableFields

type IntentMutableFields struct {
	meta.IntentMutableFields

	// IntentDeletedAt marks the usage-based base/original intent as deleted.
	// Adapters derive the effective charge DeletedAt from this value when no intent override is present.
	IntentDeletedAt *time.Time `json:"intentDeletedAt,omitempty"`

	InvoiceAt time.Time `json:"invoiceAt"`

	Price productcatalog.Price `json:"price"`

	Discounts billing.Discounts `json:"discounts"`

	// UnitConfig is the optional unit conversion snapshotted from the effective
	// rate card. Like Price it is a mutable rating input (set on create and
	// update) so re-rates read the config in effect for the charge.
	UnitConfig *productcatalog.UnitConfig `json:"unitConfig,omitempty"`
}

func (IntentMutableFields) Clone

func (IntentMutableFields) Normalized

func (IntentMutableFields) Validate

func (f IntentMutableFields) Validate() error

type OnInvoiceUsageAccruedInput

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 (OnInvoiceUsageAccruedInput) Validate

func (i OnInvoiceUsageAccruedInput) Validate() error

type OnPaymentAuthorizedInput

type OnPaymentAuthorizedInput = RunEventInput

type OnPaymentSettledInput

type OnPaymentSettledInput = RunEventInput

type OverridableIntent

type OverridableIntent struct {
	// contains filtered or unexported fields
}

OverridableIntent stores the immutable intent plus the base and optional override mutable layers. Direct layer access is error-prone because callers must manually decide which layer is active; this API centralizes that choice so reads and mutations use the correct override layer when present.

func NewOverridableIntent

func NewOverridableIntent(baseIntent Intent, overrideLayer *IntentMutableFields) OverridableIntent

func (OverridableIntent) GetBaseIntent

func (i OverridableIntent) GetBaseIntent() Intent

func (OverridableIntent) GetBaseManagedBy

func (i OverridableIntent) GetBaseManagedBy() billing.InvoiceLineManagedBy

func (OverridableIntent) GetCurrency

func (i OverridableIntent) GetCurrency() currencyx.Code

func (OverridableIntent) GetCustomerID

func (i OverridableIntent) GetCustomerID() string

func (OverridableIntent) GetDeletedAt

func (i OverridableIntent) GetDeletedAt() *time.Time

func (OverridableIntent) GetEffectiveDiscounts

func (i OverridableIntent) GetEffectiveDiscounts() billing.Discounts

GetEffectiveDiscounts returns cloned discounts from the active mutable layer, preferring the override layer when it is present.

func (OverridableIntent) GetEffectiveIntent

func (i OverridableIntent) GetEffectiveIntent() Intent

GetEffectiveIntent returns the customer-facing intent by combining the immutable intent with the active mutable layer.

WARNING: this clones and normalizes the intent and mutable fields. Prefer the narrower effective getters when only a few fields are required.

func (OverridableIntent) GetEffectiveInvoiceAt

func (i OverridableIntent) GetEffectiveInvoiceAt() time.Time

GetEffectiveInvoiceAt returns the invoice-at timestamp from the active mutable layer, preferring the override layer when it is present.

func (OverridableIntent) GetEffectiveMetaIntentMutableFields

func (i OverridableIntent) GetEffectiveMetaIntentMutableFields() meta.IntentMutableFields

GetEffectiveMetaIntentMutableFields returns the shared meta mutable fields from the active mutable layer, preferring the override layer when it is present.

func (OverridableIntent) GetEffectivePrice

func (i OverridableIntent) GetEffectivePrice() productcatalog.Price

GetEffectivePrice returns a cloned price from the active mutable layer, preferring the override layer when it is present.

func (OverridableIntent) GetEffectiveServicePeriod

func (i OverridableIntent) GetEffectiveServicePeriod() timeutil.ClosedPeriod

GetEffectiveServicePeriod returns the service period from the active mutable layer, preferring the override layer when it is present.

func (OverridableIntent) GetEffectiveUnitConfig

func (i OverridableIntent) GetEffectiveUnitConfig() *productcatalog.UnitConfig

GetEffectiveUnitConfig returns the cloned unit_config from the active mutable layer, preferring the override layer when it is present. Nil when the rate card carries no unit_config.

The override layer is a full snapshot of the effective fields (like Price/Discounts), so a nil override value means the config was cleared, not inherited from the base.

func (OverridableIntent) GetFeatureKey

func (i OverridableIntent) GetFeatureKey() string

GetFeatureKey returns the immutable usage-based feature key from the base intent. Override layers cannot change usage attribution.

func (OverridableIntent) GetIntentForTarget

func (i OverridableIntent) GetIntentForTarget(target meta.ChangeTarget) (Intent, error)

func (OverridableIntent) GetOverrideLayerMutableFields

func (i OverridableIntent) GetOverrideLayerMutableFields() *IntentMutableFields

func (OverridableIntent) GetSettlementMode

func (i OverridableIntent) GetSettlementMode() productcatalog.SettlementMode

func (OverridableIntent) GetSubscription

func (i OverridableIntent) GetSubscription() *meta.SubscriptionReference

func (OverridableIntent) GetTaxConfig

GetTaxConfig returns the immutable tax config from the base intent. Override layers cannot change tax attribution.

func (OverridableIntent) GetUniqueReferenceID

func (i OverridableIntent) GetUniqueReferenceID() *string

func (OverridableIntent) HasOverrideLayer

func (i OverridableIntent) HasOverrideLayer() bool

func (*OverridableIntent) Mutate

func (i *OverridableIntent) Mutate(target meta.ChangeTarget, editFn func(*IntentMutableFields) error) error

Mutate edits the requested intent mutable field layer.

The callback always receives a non-nil pointer to a cloned mutable-field value. The clone is written back only after it normalizes and validates, so validation errors do not partially mutate the intent.

func (*OverridableIntent) MutateEffective

func (i *OverridableIntent) MutateEffective(editFn func(*IntentMutableFields) error) error

func (OverridableIntent) Normalized

func (i OverridableIntent) Normalized() OverridableIntent

func (OverridableIntent) Validate

func (i OverridableIntent) Validate() error

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) GetUnitConfig

func (r RateableIntent) GetUnitConfig() *productcatalog.UnitConfig

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) Latest

func (r RealizationRuns) Latest() (RealizationRun, bool)

Latest returns the run with the latest service-period end. Ties are resolved by creation time so callers get the newest run for the same realized boundary. Filtering voided history is a caller decision.

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"`
	EventAt time.Time      `json:"eventAt"`
}

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)

	// Deprecated: use StatusActiveRealizationStarted. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActivePartialInvoiceStarted Status = "active.partial_invoice.started"
	// Deprecated: use StatusActiveRealizationWaitingForCollection. Kept
	// temporarily so persisted rows can load until the SQL migration rewrites
	// legacy statuses.
	StatusActivePartialInvoiceWaitingForCollection Status = "active.partial_invoice.waiting_for_collection"
	// Deprecated: use StatusActiveRealizationProcessing. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActivePartialInvoiceProcessing Status = "active.partial_invoice.processing"
	// Deprecated: use StatusActiveRealizationIssuing. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActivePartialInvoiceIssuing Status = "active.partial_invoice.issuing"
	// Deprecated: use StatusActiveRealizationCompleted. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActivePartialInvoiceCompleted         Status = "active.partial_invoice.completed"
	StatusActiveRealizationStarted              Status = "active.realization.started"
	StatusActiveRealizationWaitingForCollection Status = "active.realization.waiting_for_collection"
	StatusActiveRealizationProcessing           Status = "active.realization.processing"
	StatusActiveRealizationIssuing              Status = "active.realization.issuing"
	StatusActiveRealizationCompleted            Status = "active.realization.completed"
	// Deprecated: use StatusActiveRealizationStarted. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActiveFinalRealizationStarted Status = "active.final_realization.started"
	// Deprecated: use StatusActiveRealizationWaitingForCollection. Kept
	// temporarily so persisted rows can load until the SQL migration rewrites
	// legacy statuses.
	StatusActiveFinalRealizationWaitingForCollection Status = "active.final_realization.waiting_for_collection"
	// Deprecated: use StatusActiveRealizationProcessing. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActiveFinalRealizationProcessing Status = "active.final_realization.processing"
	// Deprecated: use StatusActiveRealizationIssuing. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActiveFinalRealizationIssuing Status = "active.final_realization.issuing"
	// Deprecated: use StatusActiveRealizationCompleted. Kept temporarily so
	// persisted rows can load until the SQL migration rewrites legacy statuses.
	StatusActiveFinalRealizationCompleted Status = "active.final_realization.completed"
	StatusActiveAwaitingPaymentSettlement Status = "active.awaiting_payment_settlement"

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

func NormalizeLegacyStatus

func NormalizeLegacyStatus(status Status) Status

NormalizeLegacyStatus maps persisted pre-unification realization statuses to the canonical active.realization.* status branch. We do this at state-machine load time so old rows keep working without keeping legacy states in the lifecycle graph. The legacy values stay accepted until a follow-up SQL migration rewrites status_detailed in storage and the enum can be tightened.

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 returns one result for each input intent, preserving input order.
	// Pending gathering-line creation relies on this to pair charge targets with
	// their source intents.
	Create(ctx context.Context, input CreateInput) ([]ChargeWithGatheringLine, error)
	// GetByIDs loads usage-based charges. Request realization expansions when
	// callers need run, detailed-line, or credit-allocation state.
	GetByIDs(ctx context.Context, input GetByIDsInput) ([]Charge, error)
	// UpdateSubscriptionItemID repairs subscription ownership metadata on the
	// base intent; it must not rewrite an active customer-facing override layer.
	UpdateSubscriptionItemID(ctx context.Context, charge Charge, newSubscriptionItemID string) (Charge, error)
	// AdvanceCharge drives one usage-based charge. Realization runs store
	// cumulative usage snapshots; billing-line quantities are mapped separately.
	AdvanceCharge(ctx context.Context, input AdvanceChargeInput) (*Charge, error)
	// TriggerPatch applies an explicit base/override target patch and then
	// reconciles invoice artifacts from the effective usage-based intent.
	TriggerPatch(ctx context.Context, charge meta.ChargeID, patch meta.Patch) (meta.TriggerPatchResult[Charge], error)
	// GetCurrentTotals calculates the current customer-facing totals from the
	// effective intent and non-voided realization history.
	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