From 72a203f4fda47d351298aa7944fc0e2e8144b6a1 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:59:35 +0200 Subject: [PATCH 1/8] feat: add effectiveAt to creditgrant --- .../src/models/schemas.ts | 2 + .../aip-client-javascript/src/models/types.ts | 24 + .../aip/src/customers/credits/grant.tsp | 14 +- api/v3/api.gen.go | 1269 +++++++++-------- api/v3/handlers/customers/credits/convert.go | 2 + api/v3/openapi.yaml | 14 + .../billing/charges/creditpurchase/charge.go | 18 +- .../charges/creditpurchase/charge_test.go | 28 + openmeter/billing/creditgrant/service.go | 2 + .../billing/creditgrant/service/service.go | 11 +- .../ledger/chargeadapter/creditpurchase.go | 11 +- .../chargeadapter/creditpurchase_test.go | 21 + test/credits/creditgrant_test.go | 48 + 13 files changed, 812 insertions(+), 652 deletions(-) diff --git a/api/spec/packages/aip-client-javascript/src/models/schemas.ts b/api/spec/packages/aip-client-javascript/src/models/schemas.ts index 40e4724c0f..a6838d465c 100644 --- a/api/spec/packages/aip-client-javascript/src/models/schemas.ts +++ b/api/spec/packages/aip-client-javascript/src/models/schemas.ts @@ -3968,6 +3968,7 @@ export const createCreditGrantRequest = z .describe( 'Draw-down priority of the grant. Lower values have higher priority.', ), + effective_at: dateTime.optional(), expires_after: iso8601Duration.optional(), key: externalResourceKey.optional(), }) @@ -4011,6 +4012,7 @@ export const creditGrant = z .describe( 'Draw-down priority of the grant. Lower values have higher priority.', ), + effective_at: dateTime.optional(), expires_after: iso8601Duration.optional(), key: externalResourceKey.optional(), expires_at: dateTime.optional(), diff --git a/api/spec/packages/aip-client-javascript/src/models/types.ts b/api/spec/packages/aip-client-javascript/src/models/types.ts index fb4191d36e..bd3a1a4e04 100644 --- a/api/spec/packages/aip-client-javascript/src/models/types.ts +++ b/api/spec/packages/aip-client-javascript/src/models/types.ts @@ -3563,6 +3563,12 @@ export interface CreateCreditGrantRequest { filters?: CreateCreditGrantFilters /** Draw-down priority of the grant. Lower values have higher priority. */ priority: number + /** + * The timestamp when the credit grant becomes effective. + * + * Defaults to the current date and time. + */ + effective_at?: string /** * The duration after which the credit grant expires. * @@ -3627,6 +3633,12 @@ export interface CreditGrant { filters?: CreditGrantFilters /** Draw-down priority of the grant. Lower values have higher priority. */ priority: number + /** + * The timestamp when the credit grant becomes effective. + * + * Defaults to the current date and time. + */ + effective_at?: string /** * The duration after which the credit grant expires. * @@ -5440,6 +5452,12 @@ export interface CreateCreditGrantRequestInput { filters?: CreateCreditGrantFilters /** Draw-down priority of the grant. Lower values have higher priority. */ priority?: number + /** + * The timestamp when the credit grant becomes effective. + * + * Defaults to the current date and time. + */ + effective_at?: string /** * The duration after which the credit grant expires. * @@ -5498,6 +5516,12 @@ export interface CreditGrantInput { filters?: CreditGrantFilters /** Draw-down priority of the grant. Lower values have higher priority. */ priority?: number + /** + * The timestamp when the credit grant becomes effective. + * + * Defaults to the current date and time. + */ + effective_at?: string /** * The duration after which the credit grant expires. * diff --git a/api/spec/packages/aip/src/customers/credits/grant.tsp b/api/spec/packages/aip/src/customers/credits/grant.tsp index ef19dbe60e..12e02eb511 100644 --- a/api/spec/packages/aip/src/customers/credits/grant.tsp +++ b/api/spec/packages/aip/src/customers/credits/grant.tsp @@ -177,13 +177,13 @@ model CreditGrant { @maxValue(1000) priority?: int16 = 10; - // /** - // * The timestamp when the credit grant becomes effective. - // * - // * Defaults to the current date and time. - // */ - // @visibility(Lifecycle.Create, Lifecycle.Read) - // effective_at?: Shared.DateTime; + /** + * The timestamp when the credit grant becomes effective. + * + * Defaults to the current date and time. + */ + @visibility(Lifecycle.Create, Lifecycle.Read) + effective_at?: Shared.DateTime; /** * The duration after which the credit grant expires. diff --git a/api/v3/api.gen.go b/api/v3/api.gen.go index dc9f1a67f4..5887f19f73 100644 --- a/api/v3/api.gen.go +++ b/api/v3/api.gen.go @@ -2519,6 +2519,11 @@ type BillingCreditGrant struct { // Maximum 1024 characters. Description *string `json:"description,omitempty"` + // EffectiveAt The timestamp when the credit grant becomes effective. + // + // Defaults to the current date and time. + EffectiveAt *DateTime `json:"effective_at,omitempty"` + // ExpiresAt The timestamp when the credit grant expires. // // Calculated from the grant effective time and `expires_after` if provided. @@ -4827,6 +4832,11 @@ type CreateCreditGrantRequest struct { // Maximum 1024 characters. Description *string `json:"description,omitempty"` + // EffectiveAt The timestamp when the credit grant becomes effective. + // + // Defaults to the current date and time. + EffectiveAt *DateTime `json:"effective_at,omitempty"` + // ExpiresAfter The duration after which the credit grant expires. // // Defaults to never expiring. @@ -12133,635 +12143,636 @@ var swaggerSpec = []string{ "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", - "x8//JwAA//+oMHjiHckEAA==", + "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", + "HGqHygQA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v3/handlers/customers/credits/convert.go b/api/v3/handlers/customers/credits/convert.go index e3b0f45739..3044a80245 100644 --- a/api/v3/handlers/customers/credits/convert.go +++ b/api/v3/handlers/customers/credits/convert.go @@ -30,6 +30,7 @@ func toAPIBillingCreditGrant(charge creditpurchase.Charge) (api.BillingCreditGra Description: charge.Intent.Description, Amount: charge.Intent.CreditAmount.String(), Currency: api.BillingCurrencyCode(charge.Intent.Currency), + EffectiveAt: charge.Intent.EffectiveAt, ExpiresAt: charge.Intent.ExpiresAt, FundingMethod: toAPIBillingCreditFundingMethod(charge.Intent.Settlement), Status: toAPIBillingCreditGrantStatus(charge), @@ -337,6 +338,7 @@ func fromAPICreateCreditGrantRequest(ns string, customerID api.ULID, body api.Cr Description: body.Description, Currency: currencyx.Code(body.Currency), Amount: amount, + EffectiveAt: body.EffectiveAt, FundingMethod: fromAPIBillingCreditFundingMethod(body.FundingMethod), Priority: body.Priority, Labels: lo.FromPtrOr(body.Labels, api.Labels{}), diff --git a/api/v3/openapi.yaml b/api/v3/openapi.yaml index 01932ce88a..20ed196503 100644 --- a/api/v3/openapi.yaml +++ b/api/v3/openapi.yaml @@ -4760,6 +4760,13 @@ components: maximum: 1000 description: Draw-down priority of the grant. Lower values have higher priority. default: 10 + effective_at: + allOf: + - $ref: '#/components/schemas/DateTime' + description: |- + The timestamp when the credit grant becomes effective. + + Defaults to the current date and time. expires_at: allOf: - $ref: '#/components/schemas/DateTime' @@ -8629,6 +8636,13 @@ components: maximum: 1000 description: Draw-down priority of the grant. Lower values have higher priority. default: 10 + effective_at: + allOf: + - $ref: '#/components/schemas/DateTime' + description: |- + The timestamp when the credit grant becomes effective. + + Defaults to the current date and time. expires_after: allOf: - $ref: '#/components/schemas/ISO8601Duration' diff --git a/openmeter/billing/charges/creditpurchase/charge.go b/openmeter/billing/charges/creditpurchase/charge.go index dc520d3e4c..80541d9ef1 100644 --- a/openmeter/billing/charges/creditpurchase/charge.go +++ b/openmeter/billing/charges/creditpurchase/charge.go @@ -15,6 +15,7 @@ import ( "github.com/openmeterio/openmeter/pkg/clock" "github.com/openmeterio/openmeter/pkg/currencyx" "github.com/openmeterio/openmeter/pkg/models" + "github.com/openmeterio/openmeter/pkg/timeutil" ) type ChargeBase struct { @@ -127,8 +128,7 @@ type IntentMutableFields struct { CreditAmount alpacadecimal.Decimal `json:"amount"` // EffectiveAt is the time at which the credit purchase is effective. - // Warning/TODO[later]: Currently this is not supported in credit purchase handler and the charge will be created - // with booked_at set to CreatedAt. + // When set, the credit purchase service period is pinned to this instant. EffectiveAt *time.Time `json:"effectiveAt"` ExpiresAt *time.Time `json:"expiresAt"` Priority *int `json:"priority"` @@ -151,6 +151,16 @@ func (f IntentMutableFields) Normalized(currency currencyx.Code) IntentMutableFi f.ExpiresAt = meta.NormalizeOptionalTimestamp(f.ExpiresAt) f.FeatureFilters = f.FeatureFilters.Normalize() + if f.EffectiveAt != nil { + period := timeutil.ClosedPeriod{ + From: lo.FromPtr(f.EffectiveAt), + To: lo.FromPtr(f.EffectiveAt), + } + f.ServicePeriod = period + f.FullServicePeriod = period + f.BillingPeriod = period + } + calc, err := currency.Calculator() if err == nil { f.CreditAmount = calc.RoundToPrecision(f.CreditAmount) @@ -193,10 +203,6 @@ func (f IntentMutableFields) Validate() error { } } - if f.EffectiveAt != nil { - return errors.New("effective at is not yet supported") - } - if f.ExpiresAt != nil && !f.ExpiresAt.After(f.CalculateEffectiveAt()) { errs = append(errs, fmt.Errorf("expires at must be after effective at")) } diff --git a/openmeter/billing/charges/creditpurchase/charge_test.go b/openmeter/billing/charges/creditpurchase/charge_test.go index 1ba5df98eb..127a274ed1 100644 --- a/openmeter/billing/charges/creditpurchase/charge_test.go +++ b/openmeter/billing/charges/creditpurchase/charge_test.go @@ -2,10 +2,38 @@ package creditpurchase import ( "testing" + "time" "github.com/stretchr/testify/require" + + "github.com/openmeterio/openmeter/openmeter/billing/charges/meta" + "github.com/openmeterio/openmeter/pkg/timeutil" ) +func TestIntentNormalizedPinsServicePeriodsToEffectiveAt(t *testing.T) { + effectiveAt := time.Date(2026, 4, 17, 11, 23, 0, 0, time.UTC) + originalPeriod := timeutil.ClosedPeriod{ + From: effectiveAt.Add(-time.Hour), + To: effectiveAt.Add(time.Hour), + } + + intent := Intent{ + Intent: meta.Intent{ + ServicePeriod: originalPeriod, + FullServicePeriod: originalPeriod, + BillingPeriod: originalPeriod, + }, + EffectiveAt: &effectiveAt, + } + + got := intent.Normalized() + + expectedPeriod := timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt} + require.Equal(t, expectedPeriod, got.ServicePeriod) + require.Equal(t, expectedPeriod, got.FullServicePeriod) + require.Equal(t, expectedPeriod, got.BillingPeriod) +} + func TestFeatureFiltersNormalize(t *testing.T) { require.Equal(t, FeatureFilters{"api-calls", "storage"}, FeatureFilters([]string{"storage", "api-calls", "storage"}).Normalize()) } diff --git a/openmeter/billing/creditgrant/service.go b/openmeter/billing/creditgrant/service.go index 5c6870fa54..a47c5cee40 100644 --- a/openmeter/billing/creditgrant/service.go +++ b/openmeter/billing/creditgrant/service.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "time" "github.com/alpacahq/alpacadecimal" @@ -59,6 +60,7 @@ type CreateInput struct { // TODO: support custom currency codes later Currency currencyx.Code Amount alpacadecimal.Decimal + EffectiveAt *time.Time Priority *int16 FundingMethod FundingMethod Purchase *PurchaseTerms diff --git a/openmeter/billing/creditgrant/service/service.go b/openmeter/billing/creditgrant/service/service.go index 3b9a05ee73..91665cc4d9 100644 --- a/openmeter/billing/creditgrant/service/service.go +++ b/openmeter/billing/creditgrant/service/service.go @@ -213,8 +213,8 @@ func (s *service) UpdateExternalSettlement(ctx context.Context, input creditgran } func toIntent(input creditgrant.CreateInput) creditpurchase.Intent { - now := clock.Now().UTC() - effectiveAt := now + effectiveAt := lo.FromPtrOr(input.EffectiveAt, clock.Now()).UTC() + period := timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt} intent := creditpurchase.Intent{ Intent: meta.Intent{ @@ -229,11 +229,12 @@ func toIntent(input creditgrant.CreateInput) creditpurchase.Intent { TaxConfig: productcatalog.TaxCodeConfigFrom(input.TaxConfig), Metadata: input.Labels, // TODO: replace with actual service period - ServicePeriod: timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt}, - BillingPeriod: timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt}, - FullServicePeriod: timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt}, + ServicePeriod: period, + BillingPeriod: period, + FullServicePeriod: period, }, CreditAmount: input.Amount, + EffectiveAt: input.EffectiveAt, ExpiresAt: calculateExpiresAt(effectiveAt, input.ExpiresAfter), Settlement: toSettlement(input), }, diff --git a/openmeter/ledger/chargeadapter/creditpurchase.go b/openmeter/ledger/chargeadapter/creditpurchase.go index 02319f00f3..4b32b2b5a9 100644 --- a/openmeter/ledger/chargeadapter/creditpurchase.go +++ b/openmeter/ledger/chargeadapter/creditpurchase.go @@ -210,6 +210,7 @@ func (h *creditPurchaseHandler) issueCreditPurchaseGroup(ctx context.Context, ch } annotations := chargeAnnotationsForCreditPurchaseCharge(charge) featureFilters := charge.Intent.FeatureFilters.Normalize() + bookedAt := charge.Intent.ServicePeriod.To advanceAttributions, err := h.advanceAttributions(ctx, customerID, charge.Intent.Currency, charge.Intent.CreditAmount, featureFilters) if err != nil { @@ -230,7 +231,7 @@ func (h *creditPurchaseHandler) issueCreditPurchaseGroup(ctx context.Context, ch for _, attribution := range advanceAttributions { templates = append(templates, transactions.AttributeCustomerAdvanceReceivableCostBasisTemplate{ - At: charge.CreatedAt, + At: bookedAt, Amount: attribution.advanceAmount, Currency: charge.Intent.Currency, CostBasis: &costBasis, @@ -240,7 +241,7 @@ func (h *creditPurchaseHandler) issueCreditPurchaseGroup(ctx context.Context, ch if attribution.accruedAmount.IsPositive() { templates = append(templates, transactions.TranslateCustomerAccruedCostBasisTemplate{ - At: charge.CreatedAt, + At: bookedAt, Amount: attribution.accruedAmount, Currency: charge.Intent.Currency, TaxCode: attribution.taxCode, @@ -253,7 +254,7 @@ func (h *creditPurchaseHandler) issueCreditPurchaseGroup(ctx context.Context, ch if issuableAmount.IsPositive() { templates = append(templates, transactions.IssueCustomerReceivableTemplate{ - At: charge.CreatedAt, + At: bookedAt, Amount: issuableAmount, Currency: charge.Intent.Currency, CostBasis: &costBasis, @@ -268,14 +269,14 @@ func (h *creditPurchaseHandler) issueCreditPurchaseGroup(ctx context.Context, ch // does not leave an unsettled receivable behind. templates = append(templates, transactions.AuthorizeCustomerReceivablePaymentTemplate{ - At: charge.CreatedAt, + At: bookedAt, Amount: charge.Intent.CreditAmount, Currency: charge.Intent.Currency, CostBasis: &costBasis, Features: featureFilters, }, transactions.SettleCustomerReceivableFromPaymentTemplate{ - At: charge.CreatedAt, + At: bookedAt, Amount: charge.Intent.CreditAmount, Currency: charge.Intent.Currency, CostBasis: &costBasis, diff --git a/openmeter/ledger/chargeadapter/creditpurchase_test.go b/openmeter/ledger/chargeadapter/creditpurchase_test.go index d50b58af41..ff1ecae921 100644 --- a/openmeter/ledger/chargeadapter/creditpurchase_test.go +++ b/openmeter/ledger/chargeadapter/creditpurchase_test.go @@ -137,6 +137,27 @@ func TestOnCreditPurchaseInitiated(t *testing.T) { require.True(t, env.sumBalance(t, env.receivableSubAccount(t, costBasis)).Equal(alpacadecimal.NewFromInt(-100))) } +func TestOnCreditPurchaseInitiated_UsesServicePeriodEndAsBookedAt(t *testing.T) { + env := newCreditPurchaseHandlerTestEnv(t) + + costBasis := mustDecimal(t, "0.5") + charge := env.newExternalCharge(alpacadecimal.NewFromInt(100), costBasis) + effectiveAt := charge.CreatedAt.Add(2 * time.Hour) + effectivePeriod := timeutil.ClosedPeriod{From: effectiveAt, To: effectiveAt} + charge.Intent.ServicePeriod = effectivePeriod + charge.Intent.FullServicePeriod = effectivePeriod + charge.Intent.BillingPeriod = effectivePeriod + + ref, err := env.handler.OnCreditPurchaseInitiated(t.Context(), charge) + require.NoError(t, err) + require.NotEmpty(t, ref.TransactionGroupID) + + for _, bookedAt := range env.transactionBookedAtTimes(t, ref.TransactionGroupID) { + requireLedgerBookedAtEqual(t, effectiveAt, bookedAt) + requireLedgerBookedAtNotEqual(t, charge.CreatedAt, bookedAt) + } +} + func TestOnCreditPurchaseInitiated_UsesFeatureRestrictedFBO(t *testing.T) { env := newCreditPurchaseHandlerTestEnv(t) diff --git a/test/credits/creditgrant_test.go b/test/credits/creditgrant_test.go index ba7d5069dd..7d3bdc3be6 100644 --- a/test/credits/creditgrant_test.go +++ b/test/credits/creditgrant_test.go @@ -22,6 +22,7 @@ import ( creditgrant "github.com/openmeterio/openmeter/openmeter/billing/creditgrant" creditgrantservice "github.com/openmeterio/openmeter/openmeter/billing/creditgrant/service" "github.com/openmeterio/openmeter/openmeter/customer" + ledgertransactiondb "github.com/openmeterio/openmeter/openmeter/ent/db/ledgertransaction" enttx "github.com/openmeterio/openmeter/openmeter/ent/tx" "github.com/openmeterio/openmeter/openmeter/ledger" ledgerbreakage "github.com/openmeterio/openmeter/openmeter/ledger/breakage" @@ -189,6 +190,53 @@ func (s *CreditGrantTestSuite) TestCreatePromotionalGrant() { s.Len(gatheringInvoices.Items, 0) } +func (s *CreditGrantTestSuite) TestCreatePromotionalGrantUsesEffectiveAtForServicePeriodAndLedgerBookedAt() { + ctx := context.Background() + ns := s.GetUniqueNamespace("creditgrant-service-promotional-effective-at") + s.ProvisionDefaultTaxCodes(ctx, ns) + + cust := s.CreateLedgerBackedCustomer(ns, "test-subject") + sandboxApp := s.InstallSandboxApp(s.T(), ns) + _ = s.ProvisionBillingProfile(ctx, ns, sandboxApp.GetID()) + + now := datetime.MustParseTimeInLocation(s.T(), "2026-04-17T11:23:00Z", time.UTC).AsTime() + effectiveAt := datetime.MustParseTimeInLocation(s.T(), "2026-04-18T09:30:00Z", time.UTC).AsTime() + clock.SetTime(now) + + grant, err := s.CreditGrantService.Create(ctx, creditgrant.CreateInput{ + Namespace: ns, + CustomerID: cust.ID, + Name: "Scheduled promotional grant", + Currency: USD, + Amount: alpacadecimal.NewFromInt(25), + EffectiveAt: &effectiveAt, + FundingMethod: creditgrant.FundingMethodNone, + }) + s.Require().NoError(err) + s.Require().NotNil(grant.Intent.EffectiveAt) + s.Equal(effectiveAt, *grant.Intent.EffectiveAt) + + expectedPeriod := grant.Intent.ServicePeriod + s.Equal(effectiveAt, expectedPeriod.From) + s.Equal(effectiveAt, expectedPeriod.To) + + s.Require().NotNil(grant.Realizations.CreditGrantRealization) + groupID := grant.Realizations.CreditGrantRealization.TransactionGroupID + transactions, err := s.DBClient.LedgerTransaction.Query(). + Where( + ledgertransactiondb.Namespace(ns), + ledgertransactiondb.GroupID(groupID), + ). + All(ctx) + s.Require().NoError(err) + s.Require().NotEmpty(transactions) + + for _, transaction := range transactions { + s.True(transaction.BookedAt.UTC().Equal(effectiveAt), "booked_at=%s effective_at=%s", transaction.BookedAt.UTC(), effectiveAt) + s.False(transaction.BookedAt.UTC().Equal(grant.CreatedAt.UTC()), "booked_at must not use wall-clock creation time") + } +} + func (s *CreditGrantTestSuite) TestCreateFeatureFilteredGrant() { ctx := context.Background() ns := s.GetUniqueNamespace("creditgrant-service-feature-filters") From 354738464e0c771e9f70af7460a5d686bc38ec06 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:06:44 +0200 Subject: [PATCH 2/8] feat(ledger): pending balance --- .../src/models/schemas.ts | 3 +- .../aip-client-javascript/src/models/types.ts | 13 +- .../aip/src/customers/credits/balance.tsp | 18 +- api/v3/api.gen.go | 668 +++++++++--------- api/v3/handlers/customers/credits/convert.go | 11 +- api/v3/openapi.yaml | 23 +- .../service/sync_credittheninvoice_test.go | 10 +- .../chargeadapter/creditpurchase_test.go | 2 +- openmeter/ledger/chargeadapter/helpers.go | 2 +- openmeter/ledger/collector/collection_fbo.go | 2 +- .../ledger/customerbalance/calculation.go | 8 +- .../customerbalance/expired_loader_test.go | 2 +- openmeter/ledger/customerbalance/facade.go | 10 +- .../ledger/customerbalance/facade_test.go | 27 +- openmeter/ledger/customerbalance/noop.go | 10 +- openmeter/ledger/customerbalance/service.go | 225 +++++- .../ledger/customerbalance/service_test.go | 129 +++- .../ledger/customerbalance/testenv_test.go | 111 ++- openmeter/ledger/historical/balance.go | 42 +- openmeter/ledger/noop/noop.go | 20 +- openmeter/ledger/primitives.go | 5 +- openmeter/ledger/query.go | 7 - openmeter/ledger/testutils/integration.go | 2 +- openmeter/ledger/transactions/collection.go | 2 +- test/credits/base.go | 22 +- test/credits/sanity_test.go | 2 +- 26 files changed, 874 insertions(+), 502 deletions(-) diff --git a/api/spec/packages/aip-client-javascript/src/models/schemas.ts b/api/spec/packages/aip-client-javascript/src/models/schemas.ts index a6838d465c..42893e5382 100644 --- a/api/spec/packages/aip-client-javascript/src/models/schemas.ts +++ b/api/spec/packages/aip-client-javascript/src/models/schemas.ts @@ -2910,8 +2910,9 @@ export const creditAdjustment = z export const creditBalance = z .object({ currency: billingCurrencyCode, + live: numeric, + settled: numeric, pending: numeric, - available: numeric, }) .describe('The credit balance by currency.') diff --git a/api/spec/packages/aip-client-javascript/src/models/types.ts b/api/spec/packages/aip-client-javascript/src/models/types.ts index bd3a1a4e04..2eba305ff6 100644 --- a/api/spec/packages/aip-client-javascript/src/models/types.ts +++ b/api/spec/packages/aip-client-javascript/src/models/types.ts @@ -2176,16 +2176,15 @@ export interface CreditAdjustment { /** The credit balance by currency. */ export interface CreditBalance { currency: string + /** Credits available after applying currently live charge impacts. */ + live: string + /** Credits that have been booked on the ledger as of the balance timestamp. */ + settled: string /** - * Credits that have been granted but cannot yet be consumed. Includes grants - * awaiting payment clearance or with a future effective date. + * Credits that have been granted but are not yet written to the ledger, or are + * written to the ledger with a future booked time. */ pending: string - /** - * Credits that can be consumed right now. Derived from cleared grants after - * applying eligibility and restriction rules. - */ - available: string } /** CreditAdjustment create request. */ diff --git a/api/spec/packages/aip/src/customers/credits/balance.tsp b/api/spec/packages/aip/src/customers/credits/balance.tsp index 9bce56fcb5..40a8d0c380 100644 --- a/api/spec/packages/aip/src/customers/credits/balance.tsp +++ b/api/spec/packages/aip/src/customers/credits/balance.tsp @@ -33,18 +33,24 @@ model CreditBalance { currency: Currencies.CurrencyCode; /** - * Credits that have been granted but cannot yet be consumed. Includes grants - * awaiting payment clearance or with a future effective date. + * Credits available after applying currently live charge impacts. */ @visibility(Lifecycle.Read) @example("200.00") - pending: Shared.Numeric; + live: Shared.Numeric; /** - * Credits that can be consumed right now. Derived from cleared grants after - * applying eligibility and restriction rules. + * Credits that have been booked on the ledger as of the balance timestamp. */ @visibility(Lifecycle.Read) @example("150.00") - available: Shared.Numeric; + settled: Shared.Numeric; + + /** + * Credits that have been granted but are not yet written to the ledger, or are + * written to the ledger with a future booked time. + */ + @visibility(Lifecycle.Read) + @example("50.00") + pending: Shared.Numeric; } diff --git a/api/v3/api.gen.go b/api/v3/api.gen.go index 5887f19f73..7b0728a027 100644 --- a/api/v3/api.gen.go +++ b/api/v3/api.gen.go @@ -5139,14 +5139,17 @@ type CreateTaxCodeRequest struct { // CreditBalance The credit balance by currency. type CreditBalance struct { - // Available Credits that can be consumed right now. Derived from cleared grants after - // applying eligibility and restriction rules. - Available Numeric `json:"available"` - Currency BillingCurrencyCode `json:"currency"` + Currency BillingCurrencyCode `json:"currency"` + + // Live Credits available after applying currently live charge impacts. + Live Numeric `json:"live"` - // Pending Credits that have been granted but cannot yet be consumed. Includes grants - // awaiting payment clearance or with a future effective date. + // Pending Credits that have been granted but are not yet written to the ledger, or are + // written to the ledger with a future booked time. Pending Numeric `json:"pending"` + + // Settled Credits that have been booked on the ledger as of the balance timestamp. + Settled Numeric `json:"settled"` } // CreditGrantPagePaginatedResponse Page paginated response. @@ -12438,7 +12441,7 @@ var swaggerSpec = []string{ "4txxqwrsy4LeHkLJQzegfknID/KWFS5FERLP1vx6zQr//SzMhuZCH3+LwBr6ZVY8OgJY7T9jVVvzUOgb", "Q7EjcmMktgANEDYIhthnVwXOoXFfkSf1B+nq2GKtxoPZvqa5FqjjjHTu9eBpmHsCRaKtHco2iHItgpZ+", "d7gHNY0k2vpmQ0EjfS0JEwoqwcuiYIkmBbthAsxmibwWHCvLYxP4/5+9t11uG0f6R28FR7VVkzwryXZe", - "5iVbW1seJ5nJzmTiHSc7tTtKyTAJSXhCARyCtK1J5cu5iXMT5y7OnZwr+Re6ARAkQYmSJduJXbW144gk", + "5iVbW1seJ5nJzmTiHSc7tTtKyTAJSXhMARyCdKxJ5cu5iXMT5y7OnZwr+Re6ARAkQYmSJduJXbW144gk", "0AC6G41G968rvhgv0LV29qgUu8MLlD7hEwhH/8qU6md48pkm8gw2RZc7qz8EWwpLobUc+GoqdOMT4Kbl", "7cLLRatnQcgWa18Fst4i9EcCi1/oVcasUVz7ZAGLz2Ls9mbK6tVvymxurMvfHm5WVQ1XzO47nYqrdaDk", "0xKXd2All9xR+6bjtk5aLznNIdkcM6UqzsRmXeh+73IwlYOWdCbXFbS1oZ1faWN1gpOZizV9adj6SkP6", @@ -12446,333 +12449,332 @@ var swaggerSpec = []string{ "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", - "HGqHygQA", + "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", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v3/handlers/customers/credits/convert.go b/api/v3/handlers/customers/credits/convert.go index 3044a80245..0ae5dd4a69 100644 --- a/api/v3/handlers/customers/credits/convert.go +++ b/api/v3/handlers/customers/credits/convert.go @@ -422,13 +422,12 @@ func fromAPIBillingCreditPurchasePaymentSettlementStatus(status api.BillingCredi } } -func toAPICreditBalance(currency currencyx.Code, balance ledger.Balance) api.CreditBalance { - // Temporary mapping while the v3 credit-balance schema still predates the - // customerbalance service's settled/live-pending semantics. +func toAPICreditBalance(currency currencyx.Code, balance customerbalance.Balance) api.CreditBalance { return api.CreditBalance{ - Currency: api.BillingCurrencyCode(currency), - Available: balance.Settled().String(), - Pending: balance.Pending().String(), + Currency: api.BillingCurrencyCode(currency), + Settled: balance.Settled().String(), + Live: balance.Live().String(), + Pending: balance.Pending().String(), } } diff --git a/api/v3/openapi.yaml b/api/v3/openapi.yaml index 20ed196503..6108387245 100644 --- a/api/v3/openapi.yaml +++ b/api/v3/openapi.yaml @@ -9046,29 +9046,34 @@ components: type: object required: - currency + - live + - settled - pending - - available properties: currency: allOf: - $ref: '#/components/schemas/BillingCurrencyCode' readOnly: true - pending: + live: allOf: - $ref: '#/components/schemas/Numeric' - description: |- - Credits that have been granted but cannot yet be consumed. Includes grants - awaiting payment clearance or with a future effective date. + description: Credits available after applying currently live charge impacts. example: '200.00' readOnly: true - available: + settled: allOf: - $ref: '#/components/schemas/Numeric' - description: |- - Credits that can be consumed right now. Derived from cleared grants after - applying eligibility and restriction rules. + description: Credits that have been booked on the ledger as of the balance timestamp. example: '150.00' readOnly: true + pending: + allOf: + - $ref: '#/components/schemas/Numeric' + description: |- + Credits that have been granted but are not yet written to the ledger, or are + written to the ledger with a future booked time. + example: '50.00' + readOnly: true additionalProperties: false description: The credit balance by currency. title: Credit balance diff --git a/openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go b/openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go index 27aaeffb8a..db36f08c22 100644 --- a/openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go +++ b/openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go @@ -8456,7 +8456,7 @@ func (s *CreditThenInvoiceTestSuite) mustCustomerFBOBalance(customerID customer. }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *CreditThenInvoiceTestSuite) mustCustomerReceivableBalance(customerID customer.CustomerID, code currencyx.Code, costBasis mo.Option[*alpacadecimal.Decimal], status ledger.TransactionAuthorizationStatus) alpacadecimal.Decimal { @@ -8472,7 +8472,7 @@ func (s *CreditThenInvoiceTestSuite) mustCustomerReceivableBalance(customerID cu }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *CreditThenInvoiceTestSuite) mustCustomerAccruedBalance(customerID customer.CustomerID, code currencyx.Code, costBasis mo.Option[*alpacadecimal.Decimal]) alpacadecimal.Decimal { @@ -8487,7 +8487,7 @@ func (s *CreditThenInvoiceTestSuite) mustCustomerAccruedBalance(customerID custo }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *CreditThenInvoiceTestSuite) mustWashBalance(namespace string, code currencyx.Code, costBasis mo.Option[*alpacadecimal.Decimal]) alpacadecimal.Decimal { @@ -8502,7 +8502,7 @@ func (s *CreditThenInvoiceTestSuite) mustWashBalance(namespace string, code curr }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *CreditThenInvoiceTestSuite) mustEarningsBalance(namespace string, code currencyx.Code) alpacadecimal.Decimal { @@ -8516,7 +8516,7 @@ func (s *CreditThenInvoiceTestSuite) mustEarningsBalance(namespace string, code }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *CreditThenInvoiceTestSuite) mustGetOnlyUsageBasedCharge(ctx context.Context, subscriptionID string) usagebased.Charge { diff --git a/openmeter/ledger/chargeadapter/creditpurchase_test.go b/openmeter/ledger/chargeadapter/creditpurchase_test.go index ff1ecae921..1660e154d1 100644 --- a/openmeter/ledger/chargeadapter/creditpurchase_test.go +++ b/openmeter/ledger/chargeadapter/creditpurchase_test.go @@ -671,7 +671,7 @@ func (e *creditPurchaseHandlerTestEnv) sumBalanceAsOf(t *testing.T, subAccount l }) require.NoError(t, err) - return balance.Settled() + return balance } func (e *creditPurchaseHandlerTestEnv) breakageRows(t *testing.T, groupID string) []*entdb.LedgerBreakageRecord { diff --git a/openmeter/ledger/chargeadapter/helpers.go b/openmeter/ledger/chargeadapter/helpers.go index 071b44cbf0..28c1440c35 100644 --- a/openmeter/ledger/chargeadapter/helpers.go +++ b/openmeter/ledger/chargeadapter/helpers.go @@ -15,5 +15,5 @@ func settledBalanceForSubAccount(ctx context.Context, querier ledger.BalanceQuer return alpacadecimal.Decimal{}, fmt.Errorf("get balance for sub-account %s: %w", subAccount.Address().SubAccountID(), err) } - return balance.Settled(), nil + return balance, nil } diff --git a/openmeter/ledger/collector/collection_fbo.go b/openmeter/ledger/collector/collection_fbo.go index b31ddc48a8..77a49762a4 100644 --- a/openmeter/ledger/collector/collection_fbo.go +++ b/openmeter/ledger/collector/collection_fbo.go @@ -292,5 +292,5 @@ func (c *accrualCollector) settledSubAccountBalance(ctx context.Context, subAcco return alpacadecimal.Decimal{}, fmt.Errorf("get balance for sub-account %s: %w", subAccount.Address().SubAccountID(), err) } - return balance.Settled(), nil + return balance, nil } diff --git a/openmeter/ledger/customerbalance/calculation.go b/openmeter/ledger/customerbalance/calculation.go index c46fd511fe..a2b4350d48 100644 --- a/openmeter/ledger/customerbalance/calculation.go +++ b/openmeter/ledger/customerbalance/calculation.go @@ -85,15 +85,15 @@ func (i Impact) UnboundedAmount() alpacadecimal.Decimal { return i.OutstandingAmount() } -type chargePendingBalanceCalculator struct{} +type chargeLiveBalanceCalculator struct{} -func (chargePendingBalanceCalculator) CalculatePendingBalance(bookedBalance alpacadecimal.Decimal, impacts []Impact) alpacadecimal.Decimal { +func (chargeLiveBalanceCalculator) CalculateLiveBalance(bookedBalance alpacadecimal.Decimal, impacts []Impact) alpacadecimal.Decimal { boundedAmount, unboundedAmount := sumImpactAmounts(impacts) // credit_then_invoice can only consume positive balance, while credit_only can drive it negative. - pendingBalance := applyBoundedAmount(bookedBalance, boundedAmount) + liveBalance := applyBoundedAmount(bookedBalance, boundedAmount) - return pendingBalance.Sub(unboundedAmount) + return liveBalance.Sub(unboundedAmount) } func sumImpactAmounts(impacts []Impact) (bounded alpacadecimal.Decimal, unbounded alpacadecimal.Decimal) { diff --git a/openmeter/ledger/customerbalance/expired_loader_test.go b/openmeter/ledger/customerbalance/expired_loader_test.go index 011435fc97..6bd357f74a 100644 --- a/openmeter/ledger/customerbalance/expired_loader_test.go +++ b/openmeter/ledger/customerbalance/expired_loader_test.go @@ -601,7 +601,7 @@ func (e *testEnv) createPromotionalCreditFunding(t *testing.T, fundedAt time.Tim servicePeriod := timeutil.ClosedPeriod{ From: fundedAt, - To: fundedAt.Add(time.Hour), + To: fundedAt, } result, err := e.creditPurchase.Create(t.Context(), creditpurchase.CreateInput{ diff --git a/openmeter/ledger/customerbalance/facade.go b/openmeter/ledger/customerbalance/facade.go index 6f6e662f0f..15f1321cf3 100644 --- a/openmeter/ledger/customerbalance/facade.go +++ b/openmeter/ledger/customerbalance/facade.go @@ -101,7 +101,7 @@ func (i GetBalanceInput) Validate() error { type BalanceByCurrency struct { Currency currencyx.Code - Balance ledger.Balance + Balance Balance } type Facade struct { @@ -139,9 +139,13 @@ func (f *Facade) GetBalances(ctx context.Context, input GetBalancesInput) ([]Bal } else { var err error - codes, err = f.service.GetFBOCurrencies(ctx, input.CustomerID) + codes, err = f.service.GetBalanceCurrencies(ctx, GetBalanceCurrenciesInput{ + CustomerID: input.CustomerID, + FeatureFilter: input.FeatureFilter, + AsOf: input.AsOf, + }) if err != nil { - return nil, fmt.Errorf("get FBO currencies: %w", err) + return nil, fmt.Errorf("get balance currencies: %w", err) } } diff --git a/openmeter/ledger/customerbalance/facade_test.go b/openmeter/ledger/customerbalance/facade_test.go index 5dae9b9318..f9caa6cd2d 100644 --- a/openmeter/ledger/customerbalance/facade_test.go +++ b/openmeter/ledger/customerbalance/facade_test.go @@ -38,11 +38,11 @@ func TestFacadeGetBalancesWithExplicitCurrencies(t *testing.T) { require.Equal(t, currencyx.Code("USD"), balances[0].Currency) require.True(t, balances[0].Balance.Settled().Equal(alpacadecimal.NewFromInt(100))) - require.True(t, balances[0].Balance.Pending().Equal(alpacadecimal.NewFromInt(70))) + require.True(t, balances[0].Balance.Live().Equal(alpacadecimal.NewFromInt(70))) require.Equal(t, currencyx.Code("EUR"), balances[1].Currency) require.True(t, balances[1].Balance.Settled().Equal(alpacadecimal.NewFromInt(200))) - require.True(t, balances[1].Balance.Pending().Equal(alpacadecimal.NewFromInt(130))) + require.True(t, balances[1].Balance.Live().Equal(alpacadecimal.NewFromInt(130))) } func TestFacadeGetBalancesWithDiscoveredCurrencies(t *testing.T) { @@ -69,11 +69,11 @@ func TestFacadeGetBalancesWithDiscoveredCurrencies(t *testing.T) { case "USD": usdCount++ require.True(t, balance.Balance.Settled().Equal(alpacadecimal.NewFromInt(100))) - require.True(t, balance.Balance.Pending().Equal(alpacadecimal.NewFromInt(70))) + require.True(t, balance.Balance.Live().Equal(alpacadecimal.NewFromInt(70))) case "EUR": eurCount++ require.True(t, balance.Balance.Settled().Equal(alpacadecimal.NewFromInt(200))) - require.True(t, balance.Balance.Pending().Equal(alpacadecimal.NewFromInt(130))) + require.True(t, balance.Balance.Live().Equal(alpacadecimal.NewFromInt(130))) } } @@ -81,6 +81,25 @@ func TestFacadeGetBalancesWithDiscoveredCurrencies(t *testing.T) { require.Equal(t, 1, eurCount) } +func TestFacadeGetBalancesDiscoversPendingGrantCurrencies(t *testing.T) { + env := newTestEnv(t) + facade, err := NewFacade(env.Service) + require.NoError(t, err) + + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(40), currencyx.Code("EUR")) + + balances, err := facade.GetBalances(t.Context(), GetBalancesInput{ + CustomerID: env.CustomerID, + }) + require.NoError(t, err) + require.Len(t, balances, 1) + + require.Equal(t, currencyx.Code("EUR"), balances[0].Currency) + require.True(t, balances[0].Balance.Settled().Equal(alpacadecimal.Zero)) + require.True(t, balances[0].Balance.Live().Equal(alpacadecimal.Zero)) + require.True(t, balances[0].Balance.Pending().Equal(alpacadecimal.NewFromInt(40))) +} + func TestFacadeGetBalancesWithUnsupportedExplicitCurrency(t *testing.T) { env := newTestEnv(t) diff --git a/openmeter/ledger/customerbalance/noop.go b/openmeter/ledger/customerbalance/noop.go index f9c437f831..f15974c744 100644 --- a/openmeter/ledger/customerbalance/noop.go +++ b/openmeter/ledger/customerbalance/noop.go @@ -5,8 +5,6 @@ import ( "github.com/alpacahq/alpacadecimal" - "github.com/openmeterio/openmeter/openmeter/customer" - "github.com/openmeterio/openmeter/openmeter/ledger" "github.com/openmeterio/openmeter/pkg/currencyx" ) @@ -16,6 +14,10 @@ func (noopBalance) Settled() alpacadecimal.Decimal { return alpacadecimal.Zero } +func (noopBalance) Live() alpacadecimal.Decimal { + return alpacadecimal.Zero +} + func (noopBalance) Pending() alpacadecimal.Decimal { return alpacadecimal.Zero } @@ -24,7 +26,7 @@ type NoopService struct{} var _ Service = NoopService{} -func (NoopService) GetBalance(context.Context, GetBalanceServiceInput) (ledger.Balance, error) { +func (NoopService) GetBalance(context.Context, GetBalanceServiceInput) (Balance, error) { return noopBalance{}, nil } @@ -32,7 +34,7 @@ func (NoopService) ListCreditTransactions(context.Context, ListCreditTransaction return ListCreditTransactionsResult{}, nil } -func (NoopService) GetFBOCurrencies(context.Context, customer.CustomerID) ([]currencyx.Code, error) { +func (NoopService) GetBalanceCurrencies(context.Context, GetBalanceCurrenciesInput) ([]currencyx.Code, error) { return nil, nil } diff --git a/openmeter/ledger/customerbalance/service.go b/openmeter/ledger/customerbalance/service.go index 05e44296f6..e8290c3be5 100644 --- a/openmeter/ledger/customerbalance/service.go +++ b/openmeter/ledger/customerbalance/service.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "slices" + "time" "github.com/alpacahq/alpacadecimal" "github.com/samber/mo" @@ -22,9 +24,15 @@ import ( ) type Service interface { - GetBalance(ctx context.Context, input GetBalanceServiceInput) (ledger.Balance, error) + GetBalance(ctx context.Context, input GetBalanceServiceInput) (Balance, error) ListCreditTransactions(ctx context.Context, input ListCreditTransactionsInput) (ListCreditTransactionsResult, error) - GetFBOCurrencies(ctx context.Context, customerID customer.CustomerID) ([]currencyx.Code, error) + GetBalanceCurrencies(ctx context.Context, input GetBalanceCurrenciesInput) ([]currencyx.Code, error) +} + +type Balance interface { + Settled() alpacadecimal.Decimal + Live() alpacadecimal.Decimal + Pending() alpacadecimal.Decimal } // ---------------------------------------------------------------------------- @@ -67,7 +75,7 @@ type service struct { BalanceQuerier ledger.BalanceQuerier Breakage ledgerbreakage.Service - balanceCalculator chargePendingBalanceCalculator + balanceCalculator chargeLiveBalanceCalculator } var _ Service = (*service)(nil) @@ -90,6 +98,12 @@ type GetBalanceServiceInput struct { BalanceQuery ledger.BalanceQuery } +type GetBalanceCurrenciesInput struct { + CustomerID customer.CustomerID + FeatureFilter mo.Option[creditpurchase.FeatureFilters] + AsOf *time.Time +} + func (i GetBalanceServiceInput) Validate() error { var errs []error @@ -133,6 +147,40 @@ func (i GetBalanceServiceInput) balanceQuery() ledger.BalanceQuery { return query } +func (i GetBalanceServiceInput) pendingGrantAsOf() time.Time { + if i.BalanceQuery.AsOf != nil { + return *i.BalanceQuery.AsOf + } + + return clock.Now() +} + +func (i GetBalanceCurrenciesInput) Validate() error { + var errs []error + + if err := i.CustomerID.Validate(); err != nil { + errs = append(errs, fmt.Errorf("customer ID: %w", err)) + } + + if err := ValidateFeatureFilter(i.FeatureFilter); err != nil { + errs = append(errs, fmt.Errorf("feature filter: %w", err)) + } + + if i.AsOf != nil && i.AsOf.IsZero() { + errs = append(errs, errors.New("asOf must not be zero")) + } + + return models.NewNillableGenericValidationError(errors.Join(errs...)) +} + +func (i GetBalanceCurrenciesInput) pendingGrantAsOf() time.Time { + if i.AsOf != nil { + return *i.AsOf + } + + return clock.Now() +} + func (i GetBalanceServiceInput) bookedRoute() ledger.RouteFilter { route := i.featureRoute() route.Currency = i.Currency @@ -205,11 +253,11 @@ func New(config Config) (*service, error) { Ledger: config.Ledger, BalanceQuerier: config.BalanceQuerier, Breakage: breakageService, - balanceCalculator: chargePendingBalanceCalculator{}, + balanceCalculator: chargeLiveBalanceCalculator{}, }, nil } -func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) (ledger.Balance, error) { +func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) (Balance, error) { if err := input.Validate(); err != nil { return nil, err } @@ -230,22 +278,46 @@ func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) return nil, fmt.Errorf("get advance balance: %w", err) } - // Pending balance remains a current projection from open charges. - // Historical cursor/as-of filtering only affects the booked/settled side for now. - impacts, err := s.getChargePendingBalanceImpacts(ctx, input.CustomerID, input.Currency, normalizeFeatureFilter(input.FeatureFilter)) + // Live balance remains a current projection from open charges. + // Historical cursor/as-of filtering only affects the booked/available side for now. + impacts, err := s.getChargeLiveBalanceImpacts(ctx, input.CustomerID, input.Currency, normalizeFeatureFilter(input.FeatureFilter)) if err != nil { - return nil, fmt.Errorf("get charge pending balance impacts: %w", err) + return nil, fmt.Errorf("get charge live balance impacts: %w", err) } - settled := bookedBalance.Settled().Add(advanceBalance.Settled()) + pending, err := s.getPendingGrantAmount(ctx, input.CustomerID, input.Currency, normalizeFeatureFilter(input.FeatureFilter), input.pendingGrantAsOf()) + if err != nil { + return nil, fmt.Errorf("get pending grant amount: %w", err) + } + + settled := bookedBalance.Add(advanceBalance) return balance{ settled: settled, - pending: s.balanceCalculator.CalculatePendingBalance(settled, impacts), + live: s.balanceCalculator.CalculateLiveBalance(settled, impacts), + pending: pending, }, nil } -func (s *service) GetFBOCurrencies(ctx context.Context, customerID customer.CustomerID) ([]currencyx.Code, error) { +func (s *service) GetBalanceCurrencies(ctx context.Context, input GetBalanceCurrenciesInput) ([]currencyx.Code, error) { + if err := input.Validate(); err != nil { + return nil, err + } + + fboCurrencies, err := s.getFBOCurrencies(ctx, input.CustomerID) + if err != nil { + return nil, err + } + + pendingCurrencies, err := s.getPendingGrantCurrencies(ctx, input.CustomerID, normalizeFeatureFilter(input.FeatureFilter), input.pendingGrantAsOf()) + if err != nil { + return nil, err + } + + return dedupeCurrencies(append(fboCurrencies, pendingCurrencies...)), nil +} + +func (s *service) getFBOCurrencies(ctx context.Context, customerID customer.CustomerID) ([]currencyx.Code, error) { customerAccounts, err := s.AccountResolver.GetCustomerAccounts(ctx, customerID) if err != nil { return nil, fmt.Errorf("get customer accounts: %w", err) @@ -275,7 +347,125 @@ func (s *service) GetFBOCurrencies(ctx context.Context, customerID customer.Cust return codes, nil } -func (s *service) getChargePendingBalanceImpacts(ctx context.Context, customerID customer.CustomerID, currency currencyx.Code, featureFilter mo.Option[creditpurchase.FeatureFilters]) ([]Impact, error) { +func (s *service) getPendingGrantCurrencies( + ctx context.Context, + customerID customer.CustomerID, + featureFilter mo.Option[creditpurchase.FeatureFilters], + asOf time.Time, +) ([]currencyx.Code, error) { + charges, err := s.listPendingGrantCandidateCharges(ctx, customerID) + if err != nil { + return nil, err + } + + codes := make([]currencyx.Code, 0, len(charges)) + for _, charge := range charges { + creditPurchaseCharge, err := charge.AsCreditPurchaseCharge() + if err != nil { + return nil, fmt.Errorf("map credit purchase charge: %w", err) + } + + if !isPendingGrantAt(creditPurchaseCharge, asOf) { + continue + } + + if !featureFilterMatchesCreditPurchase(featureFilter, creditPurchaseCharge.Intent.FeatureFilters) { + continue + } + + codes = append(codes, creditPurchaseCharge.Intent.Currency) + } + + return dedupeCurrencies(codes), nil +} + +func (s *service) getPendingGrantAmount( + ctx context.Context, + customerID customer.CustomerID, + currency currencyx.Code, + featureFilter mo.Option[creditpurchase.FeatureFilters], + asOf time.Time, +) (alpacadecimal.Decimal, error) { + charges, err := s.listPendingGrantCandidateCharges(ctx, customerID) + if err != nil { + return alpacadecimal.Zero, err + } + + total := alpacadecimal.Zero + for _, charge := range charges { + creditPurchaseCharge, err := charge.AsCreditPurchaseCharge() + if err != nil { + return alpacadecimal.Zero, fmt.Errorf("map credit purchase charge: %w", err) + } + + if creditPurchaseCharge.Intent.Currency != currency { + continue + } + + if !isPendingGrantAt(creditPurchaseCharge, asOf) { + continue + } + + if !featureFilterMatchesCreditPurchase(featureFilter, creditPurchaseCharge.Intent.FeatureFilters) { + continue + } + + total = total.Add(creditPurchaseCharge.Intent.CreditAmount) + } + + return total, nil +} + +func (s *service) listPendingGrantCandidateCharges(ctx context.Context, customerID customer.CustomerID) ([]charges.Charge, error) { + items, err := pagination.CollectAll( + ctx, + pagination.NewPaginator(func(ctx context.Context, page pagination.Page) (pagination.Result[charges.Charge], error) { + return s.ChargesService.ListCharges(ctx, charges.ListChargesInput{ + Page: page, + Namespace: customerID.Namespace, + CustomerIDs: []string{customerID.ID}, + ChargeTypes: []meta.ChargeType{ + meta.ChargeTypeCreditPurchase, + }, + Expands: meta.Expands{meta.ExpandRealizations}, + }) + }), + chargeListPageSize, + ) + if err != nil { + return nil, fmt.Errorf("list credit purchase charges: %w", err) + } + + return items, nil +} + +func isPendingGrantAt(charge creditpurchase.Charge, asOf time.Time) bool { + if charge.Realizations.CreditGrantRealization == nil { + return true + } + + return charge.Intent.ServicePeriod.To.After(asOf) +} + +func featureFilterMatchesCreditPurchase(featureFilter mo.Option[creditpurchase.FeatureFilters], grantFeatures creditpurchase.FeatureFilters) bool { + if featureFilter.IsAbsent() { + return true + } + + grantFeatures = grantFeatures.Normalize() + filterFeatures := featureFilter.OrEmpty() + if filterFeatures == nil { + return len(grantFeatures) == 0 + } + + if len(grantFeatures) == 0 { + return true + } + + return len(filterFeatures) == 1 && slices.Contains(grantFeatures, filterFeatures[0]) +} + +func (s *service) getChargeLiveBalanceImpacts(ctx context.Context, customerID customer.CustomerID, currency currencyx.Code, featureFilter mo.Option[creditpurchase.FeatureFilters]) ([]Impact, error) { items, err := pagination.CollectAll( ctx, pagination.NewPaginator(func(ctx context.Context, page pagination.Page) (pagination.Result[charges.Charge], error) { @@ -299,7 +489,7 @@ func (s *service) getChargePendingBalanceImpacts(ctx context.Context, customerID impacts := make([]Impact, 0, len(items)) for _, charge := range items { - impact, err := s.getChargePendingBalanceImpact(ctx, charge, currency, featureFilter) + impact, err := s.getChargeLiveBalanceImpact(ctx, charge, currency, featureFilter) if err != nil { return nil, err } @@ -314,7 +504,7 @@ func (s *service) getChargePendingBalanceImpacts(ctx context.Context, customerID return impacts, nil } -func (s *service) getChargePendingBalanceImpact(ctx context.Context, charge charges.Charge, currency currencyx.Code, featureFilter mo.Option[creditpurchase.FeatureFilters]) (*Impact, error) { +func (s *service) getChargeLiveBalanceImpact(ctx context.Context, charge charges.Charge, currency currencyx.Code, featureFilter mo.Option[creditpurchase.FeatureFilters]) (*Impact, error) { if !chargeHasStarted(charge) { return nil, nil } @@ -425,6 +615,7 @@ func newImpactOrNil(charge charges.Charge, amount alpacadecimal.Decimal) (*Impac type balance struct { settled alpacadecimal.Decimal + live alpacadecimal.Decimal pending alpacadecimal.Decimal } @@ -432,6 +623,10 @@ func (b balance) Settled() alpacadecimal.Decimal { return b.settled } +func (b balance) Live() alpacadecimal.Decimal { + return b.live +} + func (b balance) Pending() alpacadecimal.Decimal { return b.pending } diff --git a/openmeter/ledger/customerbalance/service_test.go b/openmeter/ledger/customerbalance/service_test.go index 7a59c05e8b..24b3d7f739 100644 --- a/openmeter/ledger/customerbalance/service_test.go +++ b/openmeter/ledger/customerbalance/service_test.go @@ -151,7 +151,7 @@ func TestGetBalance(t *testing.T) { name string setup func(t *testing.T, env *testEnv) wantSettled int64 - wantPending int64 + wantLive int64 }{ { name: "flat fee credit only", @@ -161,7 +161,7 @@ func TestGetBalance(t *testing.T) { env.createFlatFeeCharge(t, alpacadecimal.NewFromInt(30), productcatalog.CreditOnlySettlementMode, env.sp()) }, wantSettled: 100, - wantPending: 70, + wantLive: 70, }, { name: "flat fee credit then invoice", @@ -171,7 +171,7 @@ func TestGetBalance(t *testing.T) { env.createFlatFeeCharge(t, alpacadecimal.NewFromInt(30), productcatalog.CreditThenInvoiceSettlementMode, env.sp()) }, wantSettled: 20, - wantPending: 0, + wantLive: 0, }, { name: "credit only charge with no starting credits creates advance", @@ -179,7 +179,7 @@ func TestGetBalance(t *testing.T) { env.createFlatFeeCharge(t, alpacadecimal.NewFromInt(30), productcatalog.CreditOnlySettlementMode, env.sp()) }, wantSettled: 0, - wantPending: -30, + wantLive: -30, }, { name: "credit only charge advance settles", @@ -189,7 +189,7 @@ func TestGetBalance(t *testing.T) { env.advanceFlatFeeCharge(t, ch) }, wantSettled: -30, - wantPending: -30, + wantLive: -30, }, { name: "usage based credit only", @@ -200,7 +200,7 @@ func TestGetBalance(t *testing.T) { env.createUsageBasedCharge(t, alpacadecimal.NewFromInt(1), productcatalog.CreditOnlySettlementMode, env.sp()) }, wantSettled: 100, - wantPending: 70, + wantLive: 70, }, { name: "usage based credit then invoice", @@ -211,7 +211,7 @@ func TestGetBalance(t *testing.T) { env.createUsageBasedCharge(t, alpacadecimal.NewFromInt(1), productcatalog.CreditThenInvoiceSettlementMode, env.sp()) }, wantSettled: 20, - wantPending: 0, + wantLive: 0, }, { name: "mixed modes are pessimistic", @@ -223,7 +223,7 @@ func TestGetBalance(t *testing.T) { env.createUsageBasedCharge(t, alpacadecimal.NewFromInt(1), productcatalog.CreditOnlySettlementMode, env.sp()) }, wantSettled: 100, - wantPending: -130, + wantLive: -130, }, { name: "future charges are excluded until service period starts", @@ -240,7 +240,7 @@ func TestGetBalance(t *testing.T) { env.createUsageBasedCharge(t, alpacadecimal.NewFromInt(1), productcatalog.CreditOnlySettlementMode, futureServicePeriod) }, wantSettled: 100, - wantPending: 100, + wantLive: 100, }, { name: "usage is settled", @@ -257,7 +257,7 @@ func TestGetBalance(t *testing.T) { env.advanceFlatFeeCharge(t, charge) }, wantSettled: 40, - wantPending: 40, + wantLive: 40, }, } @@ -273,7 +273,7 @@ func TestGetBalance(t *testing.T) { }) require.NoError(t, err) assert.True(t, balance.Settled().Equal(alpacadecimal.NewFromInt(tt.wantSettled)), "settled: %s", balance.Settled()) - assert.True(t, balance.Pending().Equal(alpacadecimal.NewFromInt(tt.wantPending)), "pending: %s", balance.Pending()) + assert.True(t, balance.Live().Equal(alpacadecimal.NewFromInt(tt.wantLive)), "live: %s", balance.Live()) }) } } @@ -378,7 +378,7 @@ func TestGetBalanceWithDifferentCurrency(t *testing.T) { }) require.NoError(t, err) require.True(t, usdBalance.Settled().Equal(alpacadecimal.NewFromInt(100))) - require.True(t, usdBalance.Pending().Equal(alpacadecimal.NewFromInt(70))) + require.True(t, usdBalance.Live().Equal(alpacadecimal.NewFromInt(70))) eurBalance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ CustomerID: env.CustomerID, @@ -387,7 +387,7 @@ func TestGetBalanceWithDifferentCurrency(t *testing.T) { }) require.NoError(t, err) require.True(t, eurBalance.Settled().Equal(alpacadecimal.NewFromInt(200))) - require.True(t, eurBalance.Pending().Equal(alpacadecimal.NewFromInt(130))) + require.True(t, eurBalance.Live().Equal(alpacadecimal.NewFromInt(130))) } func TestGetBalanceFeatureFilter(t *testing.T) { @@ -446,7 +446,7 @@ func TestGetBalanceFeatureFilter(t *testing.T) { require.NoError(t, err) require.Equal(t, tt.want, balance.Settled().InexactFloat64()) - require.Equal(t, tt.want, balance.Pending().InexactFloat64()) + require.Equal(t, tt.want, balance.Live().InexactFloat64()) }) } @@ -466,7 +466,7 @@ func TestGetBalanceFeatureFilter(t *testing.T) { Features: mo.Some([]string{"feature-a"}), }, ledger.BalanceQuery{AsOf: &now}) require.NoError(t, err) - require.Equal(t, float64(10), exactFeatureABalance.Settled().InexactFloat64()) + require.Equal(t, float64(10), exactFeatureABalance.InexactFloat64()) } func TestGetBalanceFeatureFilterPendingChargeImpacts(t *testing.T) { @@ -488,31 +488,31 @@ func TestGetBalanceFeatureFilterPendingChargeImpacts(t *testing.T) { name string filter mo.Option[creditpurchase.FeatureFilters] wantSettled float64 - wantPending float64 + wantLive float64 }{ { name: "omitted filter includes every charge impact", filter: AllFeatureFilter(), wantSettled: 130, - wantPending: 88, + wantLive: 88, }, { name: "unrestricted filter includes only unrestricted charge impacts", filter: NewUnrestrictedFeatureFilter(), wantSettled: 100, - wantPending: 95, + wantLive: 95, }, { name: "matching feature filter includes unrestricted and matching charge impacts", filter: NewFeatureFilter([]string{testFeatureKey}), wantSettled: 110, - wantPending: 68, + wantLive: 68, }, { name: "non-matching feature filter excludes restricted charge impacts for other features", filter: NewFeatureFilter([]string{"storage"}), wantSettled: 120, - wantPending: 115, + wantLive: 115, }, } @@ -526,7 +526,94 @@ func TestGetBalanceFeatureFilterPendingChargeImpacts(t *testing.T) { require.NoError(t, err) require.Equal(t, tt.wantSettled, balance.Settled().InexactFloat64()) - require.Equal(t, tt.wantPending, balance.Pending().InexactFloat64()) + require.Equal(t, tt.wantLive, balance.Live().InexactFloat64()) + }) + } +} + +func TestGetBalancePendingGrants(t *testing.T) { + env := newTestEnv(t) + + now := clock.Now() + futureEffectiveAt := now.Add(time.Hour) + + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(30), env.Currency) + env.createPromotionalCreditGrant(t, alpacadecimal.NewFromInt(20), env.Currency, &futureEffectiveAt) + env.createPromotionalCreditGrant(t, alpacadecimal.NewFromInt(10), env.Currency, nil) + + balance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ + CustomerID: env.CustomerID, + Currency: env.Currency, + FeatureFilter: AllFeatureFilter(), + BalanceQuery: ledger.BalanceQuery{ + AsOf: &now, + }, + }) + require.NoError(t, err) + + require.Equal(t, float64(10), balance.Settled().InexactFloat64()) + require.Equal(t, float64(10), balance.Live().InexactFloat64()) + require.Equal(t, float64(50), balance.Pending().InexactFloat64()) + + afterFutureEffectiveAt := futureEffectiveAt.Add(time.Second) + balance, err = env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ + CustomerID: env.CustomerID, + Currency: env.Currency, + FeatureFilter: AllFeatureFilter(), + BalanceQuery: ledger.BalanceQuery{ + AsOf: &afterFutureEffectiveAt, + }, + }) + require.NoError(t, err) + + require.Equal(t, float64(30), balance.Settled().InexactFloat64()) + require.Equal(t, float64(30), balance.Live().InexactFloat64()) + require.Equal(t, float64(30), balance.Pending().InexactFloat64()) +} + +func TestGetBalancePendingGrantFeatureFilter(t *testing.T) { + env := newTestEnv(t) + + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(100), env.Currency) + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(10), env.Currency, testFeatureKey) + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(20), env.Currency, "storage") + + tests := []struct { + name string + filter mo.Option[creditpurchase.FeatureFilters] + want float64 + }{ + { + name: "omitted filter returns all pending grants", + filter: AllFeatureFilter(), + want: 130, + }, + { + name: "unrestricted filter returns unrestricted pending grants", + filter: NewUnrestrictedFeatureFilter(), + want: 100, + }, + { + name: "matching feature filter includes unrestricted and matching pending grants", + filter: NewFeatureFilter([]string{testFeatureKey}), + want: 110, + }, + { + name: "non-matching feature filter excludes restricted pending grants for other features", + filter: NewFeatureFilter([]string{"storage"}), + want: 120, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + balance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ + CustomerID: env.CustomerID, + Currency: env.Currency, + FeatureFilter: tt.filter, + }) + require.NoError(t, err) + require.Equal(t, tt.want, balance.Pending().InexactFloat64()) }) } } diff --git a/openmeter/ledger/customerbalance/testenv_test.go b/openmeter/ledger/customerbalance/testenv_test.go index 8e40eb7608..ef71922b0e 100644 --- a/openmeter/ledger/customerbalance/testenv_test.go +++ b/openmeter/ledger/customerbalance/testenv_test.go @@ -289,9 +289,10 @@ func newTestEnv(t *testing.T) *testEnv { AccountResolver: base.Deps.ResolversService, SubAccountService: base.Deps.AccountService, ChargesService: chargeStore{ - search: searchAdapter, - flatFeeService: flatFeeService, - usageBasedService: usageService, + search: searchAdapter, + creditPurchaseService: creditPurchaseService, + flatFeeService: flatFeeService, + usageBasedService: usageService, }, CreditPurchaseSvc: creditPurchaseService, UsageBasedService: usageService, @@ -540,10 +541,74 @@ func (e *testEnv) advanceFlatFeeCharge(t *testing.T, charge flatfee.Charge) flat return *advancedCharge } +func (e *testEnv) createPendingInvoiceCreditGrant(t *testing.T, amount alpacadecimal.Decimal, currency currencyx.Code, features ...string) creditpurchase.Charge { + t.Helper() + + return e.createCreditPurchase(t, amount, currency, nil, creditpurchase.FeatureFilters(features), creditpurchase.NewSettlement(creditpurchase.InvoiceSettlement{ + GenericSettlement: creditpurchase.GenericSettlement{ + Currency: currency, + CostBasis: alpacadecimal.NewFromFloat(1), + }, + })) +} + +func (e *testEnv) createPromotionalCreditGrant(t *testing.T, amount alpacadecimal.Decimal, currency currencyx.Code, effectiveAt *time.Time, features ...string) creditpurchase.Charge { + t.Helper() + + return e.createCreditPurchase(t, amount, currency, effectiveAt, creditpurchase.FeatureFilters(features), creditpurchase.NewSettlement(creditpurchase.PromotionalSettlement{})) +} + +func (e *testEnv) createCreditPurchase( + t *testing.T, + amount alpacadecimal.Decimal, + currency currencyx.Code, + effectiveAt *time.Time, + features creditpurchase.FeatureFilters, + settlement creditpurchase.Settlement, +) creditpurchase.Charge { + t.Helper() + + periodAt := clock.Now() + if effectiveAt != nil { + periodAt = *effectiveAt + } + + servicePeriod := timeutil.ClosedPeriod{ + From: periodAt, + To: periodAt, + } + + result, err := e.creditPurchase.Create(t.Context(), creditpurchase.CreateInput{ + Namespace: e.Namespace, + Intent: creditpurchase.Intent{ + Intent: chargemeta.Intent{ + Name: "Funding", + ManagedBy: billing.SubscriptionManagedLine, + CustomerID: e.CustomerID.ID, + Currency: currency, + ServicePeriod: servicePeriod, + BillingPeriod: servicePeriod, + FullServicePeriod: servicePeriod, + TaxConfig: productcatalog.TaxCodeConfig{ + TaxCodeID: e.taxCodeID, + }, + }, + CreditAmount: amount, + EffectiveAt: effectiveAt, + FeatureFilters: features, + Settlement: settlement, + }, + }) + require.NoError(t, err) + + return result.Charge +} + type chargeStore struct { - search charges.ChargesSearchAdapter - flatFeeService flatfee.Service - usageBasedService usagebased.Service + search charges.ChargesSearchAdapter + creditPurchaseService creditpurchase.Service + flatFeeService flatfee.Service + usageBasedService usagebased.Service } func (l chargeStore) GetByIDs(ctx context.Context, input charges.GetByIDsInput) (charges.Charges, error) { @@ -553,9 +618,12 @@ func (l chargeStore) GetByIDs(ctx context.Context, input charges.GetByIDsInput) } flatFeeIDs := make([]string, 0, len(searchResult)) + creditPurchaseIDs := make([]string, 0, len(searchResult)) usageBasedIDs := make([]string, 0, len(searchResult)) for _, item := range searchResult { switch item.Type { + case chargemeta.ChargeTypeCreditPurchase: + creditPurchaseIDs = append(creditPurchaseIDs, item.ID.ID) case chargemeta.ChargeTypeFlatFee: flatFeeIDs = append(flatFeeIDs, item.ID.ID) case chargemeta.ChargeTypeUsageBased: @@ -572,6 +640,15 @@ func (l chargeStore) GetByIDs(ctx context.Context, input charges.GetByIDsInput) return nil, err } + creditPurchaseCharges, err := l.creditPurchaseService.GetByIDs(ctx, creditpurchase.GetByIDsInput{ + Namespace: input.Namespace, + IDs: creditPurchaseIDs, + Expands: input.Expands, + }) + if err != nil { + return nil, err + } + usageBasedCharges, err := l.usageBasedService.GetByIDs(ctx, usagebased.GetByIDsInput{ Namespace: input.Namespace, IDs: usageBasedIDs, @@ -581,7 +658,10 @@ func (l chargeStore) GetByIDs(ctx context.Context, input charges.GetByIDsInput) return nil, err } - chargesByID := make(map[string]charges.Charge, len(flatFeeCharges)+len(usageBasedCharges)) + chargesByID := make(map[string]charges.Charge, len(flatFeeCharges)+len(creditPurchaseCharges)+len(usageBasedCharges)) + for _, charge := range creditPurchaseCharges { + chargesByID[charge.ID] = charges.NewCharge(charge) + } for _, charge := range flatFeeCharges { chargesByID[charge.ID] = charges.NewCharge(charge) } @@ -609,9 +689,12 @@ func (l chargeStore) ListCharges(ctx context.Context, input charges.ListChargesI } flatFeeIDs := make([]string, 0, len(searchResult.Items)) + creditPurchaseIDs := make([]string, 0, len(searchResult.Items)) usageBasedIDs := make([]string, 0, len(searchResult.Items)) for _, item := range searchResult.Items { switch item.Type { + case chargemeta.ChargeTypeCreditPurchase: + creditPurchaseIDs = append(creditPurchaseIDs, item.ID.ID) case chargemeta.ChargeTypeFlatFee: flatFeeIDs = append(flatFeeIDs, item.ID.ID) case chargemeta.ChargeTypeUsageBased: @@ -628,6 +711,15 @@ func (l chargeStore) ListCharges(ctx context.Context, input charges.ListChargesI return pagination.Result[charges.Charge]{}, err } + creditPurchaseCharges, err := l.creditPurchaseService.GetByIDs(ctx, creditpurchase.GetByIDsInput{ + Namespace: input.Namespace, + IDs: creditPurchaseIDs, + Expands: input.Expands, + }) + if err != nil { + return pagination.Result[charges.Charge]{}, err + } + usageBasedCharges, err := l.usageBasedService.GetByIDs(ctx, usagebased.GetByIDsInput{ Namespace: input.Namespace, IDs: usageBasedIDs, @@ -637,7 +729,10 @@ func (l chargeStore) ListCharges(ctx context.Context, input charges.ListChargesI return pagination.Result[charges.Charge]{}, err } - chargesByID := make(map[string]charges.Charge, len(flatFeeCharges)+len(usageBasedCharges)) + chargesByID := make(map[string]charges.Charge, len(flatFeeCharges)+len(creditPurchaseCharges)+len(usageBasedCharges)) + for _, charge := range creditPurchaseCharges { + chargesByID[charge.ID] = charges.NewCharge(charge) + } for _, charge := range flatFeeCharges { chargesByID[charge.ID] = charges.NewCharge(charge) } diff --git a/openmeter/ledger/historical/balance.go b/openmeter/ledger/historical/balance.go index 14a3063f2d..91f7301bae 100644 --- a/openmeter/ledger/historical/balance.go +++ b/openmeter/ledger/historical/balance.go @@ -10,29 +10,14 @@ import ( "github.com/openmeterio/openmeter/openmeter/ledger" ) -type Balance struct { - settled alpacadecimal.Decimal - pending alpacadecimal.Decimal -} - -var _ ledger.Balance = (*Balance)(nil) - -func (b *Balance) Settled() alpacadecimal.Decimal { - return b.settled -} - -func (b *Balance) Pending() alpacadecimal.Decimal { - return b.pending -} - var _ ledger.BalanceQuerier = (*Ledger)(nil) func (l *Ledger) GetAccountBalance(ctx context.Context, account ledger.Account, route ledger.RouteFilter, query ledger.BalanceQuery) (ledger.Balance, error) { if account == nil { - return nil, fmt.Errorf("account is required") + return alpacadecimal.Zero, fmt.Errorf("account is required") } - res, err := l.sumEntries(ctx, ledger.Query{ + balance, err := l.sumEntries(ctx, ledger.Query{ Namespace: account.ID().Namespace, Filters: ledger.Filters{ After: query.After, @@ -42,41 +27,34 @@ func (l *Ledger) GetAccountBalance(ctx context.Context, account ledger.Account, }, }) if err != nil { - return nil, fmt.Errorf("failed to sum entries for account %s/%s: %w", account.ID().Namespace, account.ID().ID, err) + return alpacadecimal.Zero, fmt.Errorf("failed to sum entries for account %s/%s: %w", account.ID().Namespace, account.ID().ID, err) } - return &Balance{ - settled: res.SettledSum, - pending: res.PendingSum, - }, nil + return balance, nil } func (l *Ledger) GetSubAccountBalance(ctx context.Context, subAccount ledger.SubAccount, query ledger.BalanceQuery) (ledger.Balance, error) { if subAccount == nil { - return nil, fmt.Errorf("sub-account is required") + return alpacadecimal.Zero, fmt.Errorf("sub-account is required") } account, err := l.accountCatalog.GetAccountByID(ctx, subAccount.AccountID()) if err != nil { - return nil, fmt.Errorf("failed to get parent account for sub-account %s: %w", subAccount.Address().SubAccountID(), err) + return alpacadecimal.Zero, fmt.Errorf("failed to get parent account for sub-account %s: %w", subAccount.Address().SubAccountID(), err) } return l.GetAccountBalance(ctx, account, subAccount.Route().Filter(), query) } -func (l *Ledger) sumEntries(ctx context.Context, query ledger.Query) (ledger.QuerySummedResult, error) { +func (l *Ledger) sumEntries(ctx context.Context, query ledger.Query) (alpacadecimal.Decimal, error) { if err := query.Validate(); err != nil { - return ledger.QuerySummedResult{}, fmt.Errorf("failed to validate query: %w", err) + return alpacadecimal.Zero, fmt.Errorf("failed to validate query: %w", err) } total, err := l.repo.SumEntries(ctx, query) if err != nil { - return ledger.QuerySummedResult{}, fmt.Errorf("failed to sum ledger entries: %w", err) + return alpacadecimal.Zero, fmt.Errorf("failed to sum ledger entries: %w", err) } - // Historical ledger currently has no settled/pending separation. - return ledger.QuerySummedResult{ - SettledSum: total, - PendingSum: total, - }, nil + return total, nil } diff --git a/openmeter/ledger/noop/noop.go b/openmeter/ledger/noop/noop.go index 10405dd358..33ea20c265 100644 --- a/openmeter/ledger/noop/noop.go +++ b/openmeter/ledger/noop/noop.go @@ -16,16 +16,6 @@ import ( const noopCurrency = currencyx.Code("USD") -type balance struct{} - -func (balance) Settled() alpacadecimal.Decimal { - return alpacadecimal.Zero -} - -func (balance) Pending() alpacadecimal.Decimal { - return alpacadecimal.Zero -} - type subAccount struct { accountID models.NamespacedID accountType ledger.AccountType @@ -45,7 +35,7 @@ func (s subAccount) AccountID() models.NamespacedID { } func (subAccount) GetBalance(context.Context) (ledger.Balance, error) { - return balance{}, nil + return alpacadecimal.Zero, nil } type postingAddress struct { @@ -88,11 +78,11 @@ func (Ledger) ListTransactions(context.Context, ledger.ListTransactionsInput) (l } func (Ledger) GetAccountBalance(context.Context, ledger.Account, ledger.RouteFilter, ledger.BalanceQuery) (ledger.Balance, error) { - return balance{}, nil + return alpacadecimal.Zero, nil } func (Ledger) GetSubAccountBalance(context.Context, ledger.SubAccount, ledger.BalanceQuery) (ledger.Balance, error) { - return balance{}, nil + return alpacadecimal.Zero, nil } type AccountResolver struct{} @@ -170,7 +160,7 @@ type customerAccount struct { } func (customerAccount) GetBalance(context.Context, ledger.RouteFilter, *ledger.TransactionCursor) (ledger.Balance, error) { - return balance{}, nil + return alpacadecimal.Zero, nil } func (customerAccount) Lock(context.Context) error { @@ -214,7 +204,7 @@ type businessAccount struct { } func (businessAccount) GetBalance(context.Context, ledger.RouteFilter, *ledger.TransactionCursor) (ledger.Balance, error) { - return balance{}, nil + return alpacadecimal.Zero, nil } func (b businessAccount) ID() models.NamespacedID { diff --git a/openmeter/ledger/primitives.go b/openmeter/ledger/primitives.go index a84fa73fdf..b586a3f007 100644 --- a/openmeter/ledger/primitives.go +++ b/openmeter/ledger/primitives.go @@ -27,10 +27,7 @@ type PostingAddress interface { Route() SubAccountRoute } -type Balance interface { - Settled() alpacadecimal.Decimal - Pending() alpacadecimal.Decimal -} +type Balance = alpacadecimal.Decimal // SubAccount is an actual address you can post against. It has all required routing information provided. // Accounts describe ownership and purpose while SubAccounts parameterize the actual posting address. diff --git a/openmeter/ledger/query.go b/openmeter/ledger/query.go index 0f58ff0ee5..098b5540bd 100644 --- a/openmeter/ledger/query.go +++ b/openmeter/ledger/query.go @@ -4,8 +4,6 @@ import ( "fmt" "time" - "github.com/alpacahq/alpacadecimal" - "github.com/openmeterio/openmeter/pkg/models" "github.com/openmeterio/openmeter/pkg/pagination/v2" "github.com/openmeterio/openmeter/pkg/timeutil" @@ -108,8 +106,3 @@ type Filters struct { // one sub-account, but arbitrary RouteFilter values can match many sub-accounts. Route RouteFilter } - -type QuerySummedResult struct { - SettledSum alpacadecimal.Decimal - PendingSum alpacadecimal.Decimal -} diff --git a/openmeter/ledger/testutils/integration.go b/openmeter/ledger/testutils/integration.go index d2419fdf4a..afdbde2c01 100644 --- a/openmeter/ledger/testutils/integration.go +++ b/openmeter/ledger/testutils/integration.go @@ -233,5 +233,5 @@ func (e *IntegrationEnv) SumBalance(t *testing.T, subAccount ledger.SubAccount) sum, err := e.Deps.HistoricalLedger.GetSubAccountBalance(t.Context(), subAccount, ledger.BalanceQuery{}) require.NoError(t, err) - return sum.Settled() + return sum } diff --git a/openmeter/ledger/transactions/collection.go b/openmeter/ledger/transactions/collection.go index a4a3aa4f2b..5b534b8f11 100644 --- a/openmeter/ledger/transactions/collection.go +++ b/openmeter/ledger/transactions/collection.go @@ -135,5 +135,5 @@ func settledBalanceForSubAccount(ctx context.Context, deps ResolverDependencies, return alpacadecimal.Decimal{}, fmt.Errorf("get balance for sub-account %s: %w", subAccount.Address().SubAccountID(), err) } - return balance.Settled(), nil + return balance, nil } diff --git a/test/credits/base.go b/test/credits/base.go index dce19030fe..704a47ec6e 100644 --- a/test/credits/base.go +++ b/test/credits/base.go @@ -326,7 +326,7 @@ func (s *BaseSuite) MustCustomerFBOBalanceWithPriorityAsOf(customerID customer.C }, query) s.NoError(err) - return balance.Settled() + return balance } func (s *BaseSuite) MustCustomerFBOBalanceForFeatures(customerID customer.CustomerID, code currencyx.Code, costBasis mo.Option[*alpacadecimal.Decimal], features mo.Option[[]string]) alpacadecimal.Decimal { @@ -347,7 +347,7 @@ func (s *BaseSuite) MustCustomerFBOBalanceWithPriorityForFeatures(customerID cus }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustCustomerReceivableBalance returns customer receivable balance in a currency @@ -366,7 +366,7 @@ func (s *BaseSuite) MustCustomerReceivableBalance(customerID customer.CustomerID }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustCustomerReceivableBalanceForTaxCode returns customer receivable balance filtered by @@ -385,7 +385,7 @@ func (s *BaseSuite) MustCustomerReceivableBalanceForTaxCode(customerID customer. }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustCustomerAccruedBalanceForTaxCode returns accrued balance filtered by cost basis and tax code. @@ -402,7 +402,7 @@ func (s *BaseSuite) MustCustomerAccruedBalanceForTaxCode(customerID customer.Cus }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustCustomerAccruedBalanceForTaxConfig returns accrued balance filtered by @@ -421,7 +421,7 @@ func (s *BaseSuite) MustCustomerAccruedBalanceForTaxConfig(customerID customer.C }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustCustomerAccruedBalance returns customer accrued balance in a currency. Pass @@ -439,7 +439,7 @@ func (s *BaseSuite) MustCustomerAccruedBalance(customerID customer.CustomerID, c }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } // MustWashBalance returns aggregate wash balance in a currency. Pass mo.None() @@ -457,7 +457,7 @@ func (s *BaseSuite) MustWashBalance(namespace string, code currencyx.Code, costB }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *BaseSuite) MustEarningsBalance(namespace string, code currencyx.Code) alpacadecimal.Decimal { @@ -479,7 +479,7 @@ func (s *BaseSuite) MustEarningsBalanceForCostBasis(namespace string, code curre }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } func (s *BaseSuite) MustBreakageBalanceAsOf(namespace string, code currencyx.Code, costBasis mo.Option[*alpacadecimal.Decimal], asOf time.Time) alpacadecimal.Decimal { @@ -494,7 +494,7 @@ func (s *BaseSuite) MustBreakageBalanceAsOf(namespace string, code currencyx.Cod }, ledger.BalanceQuery{AsOf: &asOf}) s.NoError(err) - return balance.Settled() + return balance } // MustEarningsBalanceForTaxCode returns earnings balance filtered by both cost basis and tax code. @@ -511,7 +511,7 @@ func (s *BaseSuite) MustEarningsBalanceForTaxCode(namespace string, code currenc }, ledger.BalanceQuery{}) s.NoError(err) - return balance.Settled() + return balance } type LedgerSnapshotInput struct { diff --git a/test/credits/sanity_test.go b/test/credits/sanity_test.go index 48c6ab5a1a..6988543d45 100644 --- a/test/credits/sanity_test.go +++ b/test/credits/sanity_test.go @@ -3547,7 +3547,7 @@ func (s *SanitySuite) mustEarningsBalanceForTaxConfig(namespace string, code cur }, ledger.BalanceQuery{}) s.Require().NoError(err) - return balance.Settled() + return balance } // TestTaxCodeFlowsFromCreditPurchaseToEarnings verifies that credits funded by a From 01a81688c5e4999d3c98cb95931717d213f6e0f6 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Tue, 23 Jun 2026 17:23:37 +0200 Subject: [PATCH 3/8] test: customerbalance pending --- openmeter/ledger/customerbalance/service.go | 45 +++- .../ledger/customerbalance/service_test.go | 195 ++++++++++++++++++ .../ledger/customerbalance/testenv_test.go | 10 + 3 files changed, 247 insertions(+), 3 deletions(-) diff --git a/openmeter/ledger/customerbalance/service.go b/openmeter/ledger/customerbalance/service.go index e8290c3be5..e44d94b02b 100644 --- a/openmeter/ledger/customerbalance/service.go +++ b/openmeter/ledger/customerbalance/service.go @@ -365,7 +365,7 @@ func (s *service) getPendingGrantCurrencies( return nil, fmt.Errorf("map credit purchase charge: %w", err) } - if !isPendingGrantAt(creditPurchaseCharge, asOf) { + if !isPendingCreditGrantAt(creditPurchaseCharge, asOf) { continue } @@ -402,7 +402,7 @@ func (s *service) getPendingGrantAmount( continue } - if !isPendingGrantAt(creditPurchaseCharge, asOf) { + if !isPendingCreditGrantAt(creditPurchaseCharge, asOf) { continue } @@ -417,6 +417,12 @@ func (s *service) getPendingGrantAmount( } func (s *service) listPendingGrantCandidateCharges(ctx context.Context, customerID customer.CustomerID) ([]charges.Charge, error) { + // FIXME[RTE]: this is terrible and too slow. It expands and scans + // credit-purchase charges on every balance read until pending scheduled + // grants have a durable query shape. Keep query-side heuristics conservative: + // only exclude charges that definitely cannot become ledger credit, and let + // isPendingCreditGrantAt handle lifecycle edge cases like final realized + // grants booked in the future. items, err := pagination.CollectAll( ctx, pagination.NewPaginator(func(ctx context.Context, page pagination.Page) (pagination.Result[charges.Charge], error) { @@ -427,6 +433,9 @@ func (s *service) listPendingGrantCandidateCharges(ctx context.Context, customer ChargeTypes: []meta.ChargeType{ meta.ChargeTypeCreditPurchase, }, + StatusNotIn: []meta.ChargeStatus{ + meta.ChargeStatusDeleted, + }, Expands: meta.Expands{meta.ExpandRealizations}, }) }), @@ -439,7 +448,17 @@ func (s *service) listPendingGrantCandidateCharges(ctx context.Context, customer return items, nil } -func isPendingGrantAt(charge creditpurchase.Charge, asOf time.Time) bool { +// isPendingCreditGrantAt reports whether a credit purchase should contribute to +// the scheduled-grant pending amount at asOf. +// +// A charge is pending only while it can still legitimately become effective +// ledger credit and either has no credit grant realization yet, or has already +// been realized with a future ledger booking time. +func isPendingCreditGrantAt(charge creditpurchase.Charge, asOf time.Time) bool { + if !canBecomeEffectiveLedgerCreditAt(charge, asOf) { + return false + } + if charge.Realizations.CreditGrantRealization == nil { return true } @@ -447,6 +466,26 @@ func isPendingGrantAt(charge creditpurchase.Charge, asOf time.Time) bool { return charge.Intent.ServicePeriod.To.After(asOf) } +func canBecomeEffectiveLedgerCreditAt(charge creditpurchase.Charge, asOf time.Time) bool { + if charge.Status == creditpurchase.StatusDeleted || charge.IsDeletedAt(asOf) { + return false + } + + if charge.Realizations.InvoiceSettlement != nil && charge.Realizations.InvoiceSettlement.IsDeletedAt(asOf) { + return false + } + + if charge.Realizations.ExternalPaymentSettlement != nil && charge.Realizations.ExternalPaymentSettlement.IsDeletedAt(asOf) { + return false + } + + if charge.Status == creditpurchase.StatusFinal && charge.Realizations.CreditGrantRealization == nil { + return false + } + + return true +} + func featureFilterMatchesCreditPurchase(featureFilter mo.Option[creditpurchase.FeatureFilters], grantFeatures creditpurchase.FeatureFilters) bool { if featureFilter.IsAbsent() { return true diff --git a/openmeter/ledger/customerbalance/service_test.go b/openmeter/ledger/customerbalance/service_test.go index 24b3d7f739..bf2ba028f1 100644 --- a/openmeter/ledger/customerbalance/service_test.go +++ b/openmeter/ledger/customerbalance/service_test.go @@ -12,7 +12,10 @@ import ( "github.com/openmeterio/openmeter/openmeter/billing/charges" "github.com/openmeterio/openmeter/openmeter/billing/charges/creditpurchase" "github.com/openmeterio/openmeter/openmeter/billing/charges/flatfee" + chargemeta "github.com/openmeterio/openmeter/openmeter/billing/charges/meta" "github.com/openmeterio/openmeter/openmeter/billing/charges/models/creditrealization" + "github.com/openmeterio/openmeter/openmeter/billing/charges/models/ledgertransaction" + "github.com/openmeterio/openmeter/openmeter/billing/charges/models/payment" "github.com/openmeterio/openmeter/openmeter/billing/charges/usagebased" "github.com/openmeterio/openmeter/openmeter/customer" "github.com/openmeterio/openmeter/openmeter/ledger" @@ -571,6 +574,198 @@ func TestGetBalancePendingGrants(t *testing.T) { require.Equal(t, float64(30), balance.Pending().InexactFloat64()) } +func TestGetBalancePendingInvoiceGrantBeforeDraft(t *testing.T) { + env := newTestEnv(t) + + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(30), env.Currency) + + balance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ + CustomerID: env.CustomerID, + Currency: env.Currency, + FeatureFilter: AllFeatureFilter(), + }) + require.NoError(t, err) + + require.Equal(t, float64(0), balance.Settled().InexactFloat64()) + require.Equal(t, float64(0), balance.Live().InexactFloat64()) + require.Equal(t, float64(30), balance.Pending().InexactFloat64()) +} + +func TestGetBalancePendingGrantExcludesDeletedCharge(t *testing.T) { + env := newTestEnv(t) + + env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(30), env.Currency) + deletedCharge := env.createPendingInvoiceCreditGrant(t, alpacadecimal.NewFromInt(20), env.Currency) + env.markCreditPurchaseDeleted(t, deletedCharge) + + balance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ + CustomerID: env.CustomerID, + Currency: env.Currency, + FeatureFilter: AllFeatureFilter(), + }) + require.NoError(t, err) + + require.Equal(t, float64(30), balance.Pending().InexactFloat64()) +} + +func TestIsPendingCreditGrantAt(t *testing.T) { + now := clock.Now().UTC() + future := now.Add(time.Hour) + deletedBefore := now.Add(-time.Minute) + deletedAfter := now.Add(time.Minute) + currency := currencyx.Code("USD") + + newCharge := func() creditpurchase.Charge { + servicePeriod := timeutil.ClosedPeriod{ + From: future, + To: future, + } + + return creditpurchase.Charge{ + ChargeBase: creditpurchase.ChargeBase{ + ManagedResource: chargemeta.ManagedResource{ + NamespacedModel: models.NamespacedModel{Namespace: "ns"}, + ManagedModel: models.ManagedModel{ + CreatedAt: now, + UpdatedAt: now, + }, + ID: "charge-id", + }, + Status: creditpurchase.StatusCreated, + Intent: creditpurchase.Intent{ + Intent: chargemeta.Intent{ + CustomerID: "customer-id", + Currency: currency, + ServicePeriod: servicePeriod, + BillingPeriod: servicePeriod, + FullServicePeriod: servicePeriod, + }, + CreditAmount: alpacadecimal.NewFromInt(10), + Settlement: creditpurchase.NewSettlement(creditpurchase.InvoiceSettlement{ + GenericSettlement: creditpurchase.GenericSettlement{ + Currency: currency, + CostBasis: alpacadecimal.NewFromInt(1), + }, + }), + }, + }, + } + } + + realizedGrant := &ledgertransaction.TimedGroupReference{ + GroupReference: ledgertransaction.GroupReference{TransactionGroupID: "transaction-group-id"}, + Time: now, + } + + tests := []struct { + name string + asOf time.Time + edit func(*creditpurchase.Charge) + want bool + }{ + { + name: "invoice grant before draft is pending", + asOf: now, + want: true, + }, + { + name: "future realized grant is pending before booked time", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.Realizations.CreditGrantRealization = realizedGrant + charge.Status = creditpurchase.StatusActive + }, + want: true, + }, + { + name: "future realized grant is not pending at booked time", + asOf: future, + edit: func(charge *creditpurchase.Charge) { + charge.Realizations.CreditGrantRealization = realizedGrant + charge.Status = creditpurchase.StatusActive + }, + want: false, + }, + { + name: "deleted charge status is not pending", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.Status = creditpurchase.StatusDeleted + }, + want: false, + }, + { + name: "soft deleted charge is not pending after deletion time", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.DeletedAt = &deletedBefore + }, + want: false, + }, + { + name: "soft deleted charge remains pending before deletion time", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.DeletedAt = &deletedAfter + }, + want: true, + }, + { + name: "final charge without grant realization is not pending", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.Status = creditpurchase.StatusFinal + }, + want: false, + }, + { + name: "voided invoice settlement is not pending", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.Realizations.CreditGrantRealization = realizedGrant + charge.Realizations.InvoiceSettlement = &payment.Invoiced{ + Payment: payment.Payment{ + ManagedModel: models.ManagedModel{ + CreatedAt: now, + UpdatedAt: now, + DeletedAt: &deletedBefore, + }, + }, + } + }, + want: false, + }, + { + name: "voided external settlement is not pending", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.Realizations.CreditGrantRealization = realizedGrant + charge.Realizations.ExternalPaymentSettlement = &payment.External{ + Payment: payment.Payment{ + ManagedModel: models.ManagedModel{ + CreatedAt: now, + UpdatedAt: now, + DeletedAt: &deletedBefore, + }, + }, + } + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + charge := newCharge() + if tt.edit != nil { + tt.edit(&charge) + } + + require.Equal(t, tt.want, isPendingCreditGrantAt(charge, tt.asOf)) + }) + } +} + func TestGetBalancePendingGrantFeatureFilter(t *testing.T) { env := newTestEnv(t) diff --git a/openmeter/ledger/customerbalance/testenv_test.go b/openmeter/ledger/customerbalance/testenv_test.go index ef71922b0e..c87b7e535c 100644 --- a/openmeter/ledger/customerbalance/testenv_test.go +++ b/openmeter/ledger/customerbalance/testenv_test.go @@ -558,6 +558,16 @@ func (e *testEnv) createPromotionalCreditGrant(t *testing.T, amount alpacadecima return e.createCreditPurchase(t, amount, currency, effectiveAt, creditpurchase.FeatureFilters(features), creditpurchase.NewSettlement(creditpurchase.PromotionalSettlement{})) } +func (e *testEnv) markCreditPurchaseDeleted(t *testing.T, charge creditpurchase.Charge) { + t.Helper() + + _, err := e.DB.ChargeCreditPurchase.UpdateOneID(charge.ID). + SetStatus(chargemeta.ChargeStatusDeleted). + SetStatusDetailed(creditpurchase.StatusDeleted). + Save(t.Context()) + require.NoError(t, err) +} + func (e *testEnv) createCreditPurchase( t *testing.T, amount alpacadecimal.Decimal, From 357d8b7c15ba49a7d99860c68d63014841f0f551 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Wed, 24 Jun 2026 13:02:00 +0200 Subject: [PATCH 4/8] fix: pr comments --- .../customerbalance/expired_loader_test.go | 32 +++++++++++ openmeter/ledger/customerbalance/facade.go | 4 +- .../ledger/customerbalance/funded_loader.go | 4 ++ openmeter/ledger/customerbalance/noop.go | 4 ++ openmeter/ledger/customerbalance/service.go | 55 ++++++++++++++----- .../ledger/customerbalance/service_test.go | 13 ++--- .../ledger/customerbalance/transactions.go | 4 +- .../customerbalance/transactions_test.go | 13 +++++ 8 files changed, 103 insertions(+), 26 deletions(-) diff --git a/openmeter/ledger/customerbalance/expired_loader_test.go b/openmeter/ledger/customerbalance/expired_loader_test.go index 6bd357f74a..36599fbca3 100644 --- a/openmeter/ledger/customerbalance/expired_loader_test.go +++ b/openmeter/ledger/customerbalance/expired_loader_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/alpacahq/alpacadecimal" + "github.com/samber/lo" "github.com/samber/mo" "github.com/stretchr/testify/require" @@ -123,6 +124,7 @@ func TestListCreditTransactionsExpiredBreakageFeatureFilter(t *testing.T) { issuedAt := time.Date(2026, 4, 10, 9, 0, 0, 0, time.UTC) expiresAt := issuedAt.Add(10 * time.Hour) clock.FreezeTime(issuedAt) + t.Cleanup(clock.UnFreeze) for _, spec := range []struct { amount int64 @@ -318,6 +320,7 @@ func TestListCreditTransactionsFeatureFilter(t *testing.T) { consumedAt := issuedAt.Add(time.Hour) clock.FreezeTime(consumedAt) + t.Cleanup(clock.UnFreeze) charge := env.createFlatFeeCharge(t, alpacadecimal.NewFromInt(115), productcatalog.CreditOnlySettlementMode, @@ -471,6 +474,30 @@ func TestListCreditTransactionsFeatureFilter(t *testing.T) { }) } +func TestListCreditTransactionsDoesNotScanPendingGrantsForRunningBalance(t *testing.T) { + env := newTestEnv(t) + t.Cleanup(func() { + clock.UnFreeze() + clock.ResetTime() + }) + + issuedAt := time.Date(2026, 4, 10, 9, 0, 0, 0, time.UTC) + env.bookMixedCreditTransactionState(t, issuedAt, 20, 5, 10*time.Hour) + env.Service.ChargesService = noListChargesService{ChargesService: env.Service.ChargesService} + + got, err := env.Service.ListCreditTransactions(t.Context(), ListCreditTransactionsInput{ + CustomerID: env.CustomerID, + Limit: 10, + FeatureFilter: AllFeatureFilter(), + AsOf: lo.ToPtr(issuedAt.Add(2 * time.Hour)), + }) + require.NoError(t, err) + requireCreditTransactions(t, issuedAt, got.Items, []expectedCreditTransaction{ + {txType: CreditTransactionTypeConsumed, bookedAfter: 0, amount: -5, balanceBefore: 20, balanceAfter: 15}, + {txType: CreditTransactionTypeFunded, bookedAfter: 0, amount: 20, balanceBefore: 0, balanceAfter: 20}, + }) +} + type expiredListingPlanSetup struct { amount int64 release int64 @@ -506,6 +533,7 @@ func (e *testEnv) bookExpiredListingState(t *testing.T, issuedAt time.Time, spec } clock.FreezeTime(issuedAt) + t.Cleanup(clock.UnFreeze) e.bookFBOBalance(t, total) e.fundOpenReceivable(t, total) @@ -539,6 +567,7 @@ func (e *testEnv) bookExpiredListingState(t *testing.T, issuedAt time.Time, spec usageAt := issuedAt.Add(time.Hour + time.Duration(idx)*time.Minute) clock.FreezeTime(usageAt) + t.Cleanup(clock.UnFreeze) e.bookFBOUsage(t, usageAt, plan.FBOAddress, releaseAmount) releaseInput, releaseRecord, err := e.BreakageService.ReleasePlan(t.Context(), ledgerbreakage.ReleasePlanInput{ @@ -558,6 +587,7 @@ func (e *testEnv) bookExpiredListingState(t *testing.T, issuedAt time.Time, spec reopenAt := usageAt.Add(time.Minute) clock.FreezeTime(reopenAt) + t.Cleanup(clock.UnFreeze) e.bookFBORestore(t, reopenAt, reopenAmount) e.fundOpenReceivable(t, reopenAmount) @@ -589,6 +619,7 @@ func (e *testEnv) bookMixedCreditTransactionState(t *testing.T, issuedAt time.Ti consumedAt := issuedAt.Add(time.Hour) clock.FreezeTime(consumedAt) + t.Cleanup(clock.UnFreeze) charge := e.createFlatFeeCharge(t, alpacadecimal.NewFromInt(consumed), productcatalog.CreditOnlySettlementMode, e.sp()) e.advanceFlatFeeCharge(t, charge) @@ -598,6 +629,7 @@ func (e *testEnv) createPromotionalCreditFunding(t *testing.T, fundedAt time.Tim t.Helper() clock.FreezeTime(fundedAt) + t.Cleanup(clock.UnFreeze) servicePeriod := timeutil.ClosedPeriod{ From: fundedAt, diff --git a/openmeter/ledger/customerbalance/facade.go b/openmeter/ledger/customerbalance/facade.go index 15f1321cf3..9af8ec0bb7 100644 --- a/openmeter/ledger/customerbalance/facade.go +++ b/openmeter/ledger/customerbalance/facade.go @@ -181,7 +181,7 @@ func (f *Facade) GetBalance(ctx context.Context, input GetBalanceInput) (alpacad return alpacadecimal.Zero, err } - balance, err := f.service.GetBalance(ctx, GetBalanceServiceInput{ + balance, err := f.service.GetSettledBalance(ctx, GetBalanceServiceInput{ CustomerID: input.CustomerID, Currency: input.Currency, FeatureFilter: normalizeFeatureFilter(input.FeatureFilter), @@ -194,7 +194,7 @@ func (f *Facade) GetBalance(ctx context.Context, input GetBalanceInput) (alpacad return alpacadecimal.Zero, err } - return balance.Settled(), nil + return balance, nil } func (f *Facade) ListCreditTransactions(ctx context.Context, input ListCreditTransactionsInput) (ListCreditTransactionsResult, error) { diff --git a/openmeter/ledger/customerbalance/funded_loader.go b/openmeter/ledger/customerbalance/funded_loader.go index 030b697f40..5b951ae036 100644 --- a/openmeter/ledger/customerbalance/funded_loader.go +++ b/openmeter/ledger/customerbalance/funded_loader.go @@ -34,6 +34,10 @@ func (l *fundedCreditTransactionLoader) Load(ctx context.Context, input creditTr items := make([]CreditTransaction, 0, len(result.Items)) for _, activity := range result.Items { + // FIXME: this is an N+1 group lookup on the listing path. Keep it as a + // temporary bridge because the funded activity query does not expose the + // exact balance cursor yet; replace it with a batched lookup or query-side + // cursor projection when this path is hardened. balanceCursor, err := l.balanceCursorForFundedActivity(ctx, input.CustomerID.Namespace, activity) if err != nil { return creditTransactionLoaderResult{}, err diff --git a/openmeter/ledger/customerbalance/noop.go b/openmeter/ledger/customerbalance/noop.go index f15974c744..e534f4432a 100644 --- a/openmeter/ledger/customerbalance/noop.go +++ b/openmeter/ledger/customerbalance/noop.go @@ -30,6 +30,10 @@ func (NoopService) GetBalance(context.Context, GetBalanceServiceInput) (Balance, return noopBalance{}, nil } +func (NoopService) GetSettledBalance(context.Context, GetBalanceServiceInput) (alpacadecimal.Decimal, error) { + return alpacadecimal.Zero, nil +} + func (NoopService) ListCreditTransactions(context.Context, ListCreditTransactionsInput) (ListCreditTransactionsResult, error) { return ListCreditTransactionsResult{}, nil } diff --git a/openmeter/ledger/customerbalance/service.go b/openmeter/ledger/customerbalance/service.go index e44d94b02b..6be231868c 100644 --- a/openmeter/ledger/customerbalance/service.go +++ b/openmeter/ledger/customerbalance/service.go @@ -25,6 +25,7 @@ import ( type Service interface { GetBalance(ctx context.Context, input GetBalanceServiceInput) (Balance, error) + GetSettledBalance(ctx context.Context, input GetBalanceServiceInput) (alpacadecimal.Decimal, error) ListCreditTransactions(ctx context.Context, input ListCreditTransactionsInput) (ListCreditTransactionsResult, error) GetBalanceCurrencies(ctx context.Context, input GetBalanceCurrenciesInput) ([]currencyx.Code, error) } @@ -261,21 +262,10 @@ func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) if err := input.Validate(); err != nil { return nil, err } - query := input.balanceQuery() - - customerAccounts, err := s.AccountResolver.GetCustomerAccounts(ctx, input.CustomerID) - if err != nil { - return nil, fmt.Errorf("get customer accounts: %w", err) - } - - bookedBalance, err := s.BalanceQuerier.GetAccountBalance(ctx, customerAccounts.FBOAccount, input.bookedRoute(), query) - if err != nil { - return nil, fmt.Errorf("get booked balance: %w", err) - } - advanceBalance, err := s.BalanceQuerier.GetAccountBalance(ctx, customerAccounts.ReceivableAccount, input.advanceRoute(), query) + settled, err := s.getSettledBalance(ctx, input) if err != nil { - return nil, fmt.Errorf("get advance balance: %w", err) + return nil, err } // Live balance remains a current projection from open charges. @@ -290,8 +280,6 @@ func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) return nil, fmt.Errorf("get pending grant amount: %w", err) } - settled := bookedBalance.Add(advanceBalance) - return balance{ settled: settled, live: s.balanceCalculator.CalculateLiveBalance(settled, impacts), @@ -299,11 +287,44 @@ func (s *service) GetBalance(ctx context.Context, input GetBalanceServiceInput) }, nil } +func (s *service) GetSettledBalance(ctx context.Context, input GetBalanceServiceInput) (alpacadecimal.Decimal, error) { + if err := input.Validate(); err != nil { + return alpacadecimal.Zero, err + } + + return s.getSettledBalance(ctx, input) +} + +func (s *service) getSettledBalance(ctx context.Context, input GetBalanceServiceInput) (alpacadecimal.Decimal, error) { + query := input.balanceQuery() + + customerAccounts, err := s.AccountResolver.GetCustomerAccounts(ctx, input.CustomerID) + if err != nil { + return alpacadecimal.Zero, fmt.Errorf("get customer accounts: %w", err) + } + + bookedBalance, err := s.BalanceQuerier.GetAccountBalance(ctx, customerAccounts.FBOAccount, input.bookedRoute(), query) + if err != nil { + return alpacadecimal.Zero, fmt.Errorf("get booked balance: %w", err) + } + + advanceBalance, err := s.BalanceQuerier.GetAccountBalance(ctx, customerAccounts.ReceivableAccount, input.advanceRoute(), query) + if err != nil { + return alpacadecimal.Zero, fmt.Errorf("get advance balance: %w", err) + } + + return bookedBalance.Add(advanceBalance), nil +} + func (s *service) GetBalanceCurrencies(ctx context.Context, input GetBalanceCurrenciesInput) ([]currencyx.Code, error) { if err := input.Validate(); err != nil { return nil, err } + // FIXME[RTE]: when GetBalances discovers currencies, pending grants are + // scanned here and then scanned again once per currency in GetBalance. This + // is accepted as temporary bridge behavior until scheduled grants have an + // RTE-owned fact/index or a shared candidate cache in this service. fboCurrencies, err := s.getFBOCurrencies(ctx, input.CustomerID) if err != nil { return nil, err @@ -479,6 +500,10 @@ func canBecomeEffectiveLedgerCreditAt(charge creditpurchase.Charge, asOf time.Ti return false } + // CreditGrantRealization is a successful ledger transaction reference, not a + // realization state machine. Failed grant writes leave it unset; voided + // settlement paths are represented by deleted charge/payment realizations + // above. if charge.Status == creditpurchase.StatusFinal && charge.Realizations.CreditGrantRealization == nil { return false } diff --git a/openmeter/ledger/customerbalance/service_test.go b/openmeter/ledger/customerbalance/service_test.go index bf2ba028f1..0ad3f0f4fd 100644 --- a/openmeter/ledger/customerbalance/service_test.go +++ b/openmeter/ledger/customerbalance/service_test.go @@ -6,7 +6,6 @@ import ( "github.com/alpacahq/alpacadecimal" "github.com/samber/mo" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/openmeterio/openmeter/openmeter/billing/charges" @@ -275,8 +274,8 @@ func TestGetBalance(t *testing.T) { FeatureFilter: AllFeatureFilter(), }) require.NoError(t, err) - assert.True(t, balance.Settled().Equal(alpacadecimal.NewFromInt(tt.wantSettled)), "settled: %s", balance.Settled()) - assert.True(t, balance.Live().Equal(alpacadecimal.NewFromInt(tt.wantLive)), "live: %s", balance.Live()) + require.Equal(t, float64(tt.wantSettled), balance.Settled().InexactFloat64(), "settled: %s", balance.Settled()) + require.Equal(t, float64(tt.wantLive), balance.Live().InexactFloat64(), "live: %s", balance.Live()) }) } } @@ -380,8 +379,8 @@ func TestGetBalanceWithDifferentCurrency(t *testing.T) { FeatureFilter: AllFeatureFilter(), }) require.NoError(t, err) - require.True(t, usdBalance.Settled().Equal(alpacadecimal.NewFromInt(100))) - require.True(t, usdBalance.Live().Equal(alpacadecimal.NewFromInt(70))) + require.Equal(t, float64(100), usdBalance.Settled().InexactFloat64()) + require.Equal(t, float64(70), usdBalance.Live().InexactFloat64()) eurBalance, err := env.Service.GetBalance(t.Context(), GetBalanceServiceInput{ CustomerID: env.CustomerID, @@ -389,8 +388,8 @@ func TestGetBalanceWithDifferentCurrency(t *testing.T) { FeatureFilter: AllFeatureFilter(), }) require.NoError(t, err) - require.True(t, eurBalance.Settled().Equal(alpacadecimal.NewFromInt(200))) - require.True(t, eurBalance.Live().Equal(alpacadecimal.NewFromInt(130))) + require.Equal(t, float64(200), eurBalance.Settled().InexactFloat64()) + require.Equal(t, float64(130), eurBalance.Live().InexactFloat64()) } func TestGetBalanceFeatureFilter(t *testing.T) { diff --git a/openmeter/ledger/customerbalance/transactions.go b/openmeter/ledger/customerbalance/transactions.go index 5a460e0297..f5231f5d96 100644 --- a/openmeter/ledger/customerbalance/transactions.go +++ b/openmeter/ledger/customerbalance/transactions.go @@ -181,7 +181,7 @@ func (s *service) ListCreditTransactions(ctx context.Context, input ListCreditTr s.applyChargeMetadataToCreditTransactions(ctx, input.CustomerID.Namespace, items) if len(items) > 0 { - runningBalance, err := s.GetBalance(ctx, GetBalanceServiceInput{ + runningBalance, err := s.GetSettledBalance(ctx, GetBalanceServiceInput{ CustomerID: input.CustomerID, Currency: items[0].Currency, FeatureFilter: normalizeFeatureFilter(input.FeatureFilter), @@ -191,7 +191,7 @@ func (s *service) ListCreditTransactions(ctx context.Context, input ListCreditTr return ListCreditTransactionsResult{}, fmt.Errorf("get FBO balance after transaction %s: %w", items[0].ID.ID, err) } - applyCreditTransactionBalances(items, runningBalance.Settled()) + applyCreditTransactionBalances(items, runningBalance) } var ( diff --git a/openmeter/ledger/customerbalance/transactions_test.go b/openmeter/ledger/customerbalance/transactions_test.go index 4e14119be4..9ce6623ffe 100644 --- a/openmeter/ledger/customerbalance/transactions_test.go +++ b/openmeter/ledger/customerbalance/transactions_test.go @@ -2,6 +2,7 @@ package customerbalance import ( "context" + "errors" "testing" "time" @@ -220,3 +221,15 @@ func (s staticChargeService) GetByIDs(_ context.Context, input charges.GetByIDsI func (s staticChargeService) ListCharges(context.Context, charges.ListChargesInput) (pagination.Result[charges.Charge], error) { return pagination.Result[charges.Charge]{}, nil } + +type noListChargesService struct { + ChargesService chargesService +} + +func (s noListChargesService) GetByIDs(ctx context.Context, input charges.GetByIDsInput) (charges.Charges, error) { + return s.ChargesService.GetByIDs(ctx, input) +} + +func (s noListChargesService) ListCharges(context.Context, charges.ListChargesInput) (pagination.Result[charges.Charge], error) { + return pagination.Result[charges.Charge]{}, errors.New("ListCharges must not be called") +} From def608c6c2334389fac81b44a37af6474759b391 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:16:56 +0200 Subject: [PATCH 5/8] test(ledger): align credit purchase intent fixtures --- .../ledger/customerbalance/service_test.go | 26 +++++++++------- .../ledger/customerbalance/testenv_test.go | 30 +++++++++++-------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/openmeter/ledger/customerbalance/service_test.go b/openmeter/ledger/customerbalance/service_test.go index 0ad3f0f4fd..9a2a70f528 100644 --- a/openmeter/ledger/customerbalance/service_test.go +++ b/openmeter/ledger/customerbalance/service_test.go @@ -633,19 +633,23 @@ func TestIsPendingCreditGrantAt(t *testing.T) { Status: creditpurchase.StatusCreated, Intent: creditpurchase.Intent{ Intent: chargemeta.Intent{ - CustomerID: "customer-id", - Currency: currency, - ServicePeriod: servicePeriod, - BillingPeriod: servicePeriod, - FullServicePeriod: servicePeriod, + CustomerID: "customer-id", + Currency: currency, }, - CreditAmount: alpacadecimal.NewFromInt(10), - Settlement: creditpurchase.NewSettlement(creditpurchase.InvoiceSettlement{ - GenericSettlement: creditpurchase.GenericSettlement{ - Currency: currency, - CostBasis: alpacadecimal.NewFromInt(1), + IntentMutableFields: creditpurchase.IntentMutableFields{ + IntentMutableFields: chargemeta.IntentMutableFields{ + ServicePeriod: servicePeriod, + BillingPeriod: servicePeriod, + FullServicePeriod: servicePeriod, }, - }), + CreditAmount: alpacadecimal.NewFromInt(10), + Settlement: creditpurchase.NewSettlement(creditpurchase.InvoiceSettlement{ + GenericSettlement: creditpurchase.GenericSettlement{ + Currency: currency, + CostBasis: alpacadecimal.NewFromInt(1), + }, + }), + }, }, }, } diff --git a/openmeter/ledger/customerbalance/testenv_test.go b/openmeter/ledger/customerbalance/testenv_test.go index c87b7e535c..c7ff16520d 100644 --- a/openmeter/ledger/customerbalance/testenv_test.go +++ b/openmeter/ledger/customerbalance/testenv_test.go @@ -592,21 +592,25 @@ func (e *testEnv) createCreditPurchase( Namespace: e.Namespace, Intent: creditpurchase.Intent{ Intent: chargemeta.Intent{ - Name: "Funding", - ManagedBy: billing.SubscriptionManagedLine, - CustomerID: e.CustomerID.ID, - Currency: currency, - ServicePeriod: servicePeriod, - BillingPeriod: servicePeriod, - FullServicePeriod: servicePeriod, - TaxConfig: productcatalog.TaxCodeConfig{ - TaxCodeID: e.taxCodeID, + ManagedBy: billing.SubscriptionManagedLine, + CustomerID: e.CustomerID.ID, + Currency: currency, + }, + IntentMutableFields: creditpurchase.IntentMutableFields{ + IntentMutableFields: chargemeta.IntentMutableFields{ + Name: "Funding", + ServicePeriod: servicePeriod, + BillingPeriod: servicePeriod, + FullServicePeriod: servicePeriod, + TaxConfig: productcatalog.TaxCodeConfig{ + TaxCodeID: e.taxCodeID, + }, }, + CreditAmount: amount, + EffectiveAt: effectiveAt, + FeatureFilters: features, + Settlement: settlement, }, - CreditAmount: amount, - EffectiveAt: effectiveAt, - FeatureFilters: features, - Settlement: settlement, }, }) require.NoError(t, err) From 9818aa0a921aecf467c8232c964c1f4e81e1be67 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:01:23 +0200 Subject: [PATCH 6/8] fix: align credit balance tests --- e2e/billinginvoice_override_test.go | 6 +++--- .../billing/charges/creditpurchase/charge_test.go | 12 +++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/e2e/billinginvoice_override_test.go b/e2e/billinginvoice_override_test.go index 1d546499e2..b7620a5173 100644 --- a/e2e/billinginvoice_override_test.go +++ b/e2e/billinginvoice_override_test.go @@ -772,7 +772,7 @@ func requireInvoiceTotals(t *testing.T, expected expectedInvoiceTotals, totals a }) } -func requireCustomerCreditBalance(t *testing.T, balance *apiv3.BillingCreditBalances, currency string, expectedAvailable float64, expectedPending float64) { +func requireCustomerCreditBalance(t *testing.T, balance *apiv3.BillingCreditBalances, currency string, expectedSettled float64, expectedPending float64) { t.Helper() idx := slices.IndexFunc(balance.Balances, func(item apiv3.CreditBalance) bool { @@ -780,9 +780,9 @@ func requireCustomerCreditBalance(t *testing.T, balance *apiv3.BillingCreditBala }) require.NotEqual(t, -1, idx, "credit balance for %s", currency) - available := numericToFloat(t, balance.Balances[idx].Available) + settled := numericToFloat(t, balance.Balances[idx].Settled) pending := numericToFloat(t, balance.Balances[idx].Pending) - require.Equal(t, expectedAvailable, available, "available credit balance for %s", currency) + require.Equal(t, expectedSettled, settled, "settled credit balance for %s", currency) require.Equal(t, expectedPending, pending, "pending credit balance for %s", currency) } diff --git a/openmeter/billing/charges/creditpurchase/charge_test.go b/openmeter/billing/charges/creditpurchase/charge_test.go index 127a274ed1..d54c5b906e 100644 --- a/openmeter/billing/charges/creditpurchase/charge_test.go +++ b/openmeter/billing/charges/creditpurchase/charge_test.go @@ -18,12 +18,14 @@ func TestIntentNormalizedPinsServicePeriodsToEffectiveAt(t *testing.T) { } intent := Intent{ - Intent: meta.Intent{ - ServicePeriod: originalPeriod, - FullServicePeriod: originalPeriod, - BillingPeriod: originalPeriod, + IntentMutableFields: IntentMutableFields{ + IntentMutableFields: meta.IntentMutableFields{ + ServicePeriod: originalPeriod, + FullServicePeriod: originalPeriod, + BillingPeriod: originalPeriod, + }, + EffectiveAt: &effectiveAt, }, - EffectiveAt: &effectiveAt, } got := intent.Normalized() From 3aeb6db496f46bf350cc11e0161cb671eadef68c Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:11:22 +0200 Subject: [PATCH 7/8] fix: align e2e pending balance expectation --- e2e/billinginvoice_override_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/billinginvoice_override_test.go b/e2e/billinginvoice_override_test.go index b7620a5173..767370badf 100644 --- a/e2e/billinginvoice_override_test.go +++ b/e2e/billinginvoice_override_test.go @@ -326,7 +326,7 @@ func TestInvoiceEditFlatFeeManualOverrides(t *testing.T) { status, balance, problem := c.GetCustomerCreditBalance(customer.Id) require.Equal(t, http.StatusOK, status, "problem: %+v", problem) require.NotNil(t, balance) - requireCustomerCreditBalance(t, balance, "USD", 76, 76) + requireCustomerCreditBalance(t, balance, "USD", 76, 0) activeCharges := listChargesByName(t, c, customer.Id, []apiv3.BillingChargeStatus{ apiv3.BillingChargeStatusCreated, From a2b74a467a3405dedb77fc3fc25b639c2352f3c2 Mon Sep 17 00:00:00 2001 From: Alex Goth <64845621+GAlexIHU@users.noreply.github.com> Date: Mon, 29 Jun 2026 16:37:07 +0200 Subject: [PATCH 8/8] fix: pending grant asof --- openmeter/ledger/customerbalance/service.go | 4 ++++ openmeter/ledger/customerbalance/service_test.go | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/openmeter/ledger/customerbalance/service.go b/openmeter/ledger/customerbalance/service.go index 6be231868c..f408d85677 100644 --- a/openmeter/ledger/customerbalance/service.go +++ b/openmeter/ledger/customerbalance/service.go @@ -488,6 +488,10 @@ func isPendingCreditGrantAt(charge creditpurchase.Charge, asOf time.Time) bool { } func canBecomeEffectiveLedgerCreditAt(charge creditpurchase.Charge, asOf time.Time) bool { + if charge.CreatedAt.After(asOf) { + return false + } + if charge.Status == creditpurchase.StatusDeleted || charge.IsDeletedAt(asOf) { return false } diff --git a/openmeter/ledger/customerbalance/service_test.go b/openmeter/ledger/customerbalance/service_test.go index 9a2a70f528..60a5972f92 100644 --- a/openmeter/ledger/customerbalance/service_test.go +++ b/openmeter/ledger/customerbalance/service_test.go @@ -671,6 +671,14 @@ func TestIsPendingCreditGrantAt(t *testing.T) { asOf: now, want: true, }, + { + name: "charge created after as of is not pending", + asOf: now, + edit: func(charge *creditpurchase.Charge) { + charge.CreatedAt = future + }, + want: false, + }, { name: "future realized grant is pending before booked time", asOf: now,