Skip to content

Fix CTI ledger booking timestamps#4397

Merged
turip merged 5 commits into
mainfrom
fix/cti-booked-at-missmatches
May 21, 2026
Merged

Fix CTI ledger booking timestamps#4397
turip merged 5 commits into
mainfrom
fix/cti-booked-at-missmatches

Conversation

@turip
Copy link
Copy Markdown
Member

@turip turip commented May 20, 2026

Business impact

Credit-then-invoice and credit-only charge flows now book ledger transactions at the domain event time they represent instead of deriving timestamps inside the ledger adapter. This makes customer balances and revenue staging auditable by service period:

  • flat fee in-advance usage books at the service period start
  • flat fee in-arrears usage books at the service period end
  • usage-based run allocations, accruals, and corrections book at the run service period end
  • payment authorization and settlement book at the payment event time

This prevents balance history from drifting to invoice dates, stored-at cutoffs, or wall-clock correction times, which is especially important for credit allocation, rollback, and subscription sync validation.

Technical notes

  • Moves booking timestamps into charge handler inputs (BookedAt / EventAt) and validates they are explicitly supplied.
  • Centralizes flat-fee usage booking with flatfee.UsageBookedAt.
  • Aligns usage-based credit-only and CTI reconciliation to use run service period end.
  • Extends chargeadapter and subscription-sync assertions to validate ledger transaction booking dates.

Validation

  • make lint-go-fast
  • env POSTGRES_HOST=127.0.0.1 make test-nocache

Summary by CodeRabbit

  • Refactor
    • Handlers and services now accept validated event inputs carrying explicit EventAt/BookedAt timestamps; ledger entries use these input-driven booking times.
  • Bug Fixes
    • Payment flows capture a single event timestamp per operation to avoid timing inconsistencies between authorization and settlement.
  • New Features
    • Booking time logic now respects payment terms when determining ledger booking timestamps.
  • Tests
    • Tests updated to pass/validate timestamps and assert ledger BookedAt behavior; missing-timestamp validations added.

Review Change Stack

@turip turip requested a review from a team as a code owner May 20, 2026 11:03
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ffa24cba-bd72-4a8c-9097-2fe218075a6a

📥 Commits

Reviewing files that changed from the base of the PR and between 62d36a8 and e910997.

📒 Files selected for processing (1)
  • openmeter/ledger/chargeadapter/bookedat_test.go

📝 Walkthrough

Walkthrough

Handler DTOs now carry validated timestamps: payments use EventAt, allocations/accruals use BookedAt. Services compute or derive a single event timestamp per operation (or derive BookedAt from service period and payment term), pass validated inputs to handlers, and ledger adapters use those timestamps for transaction booking. Tests and mocks updated to the new contracts.

Changes

Event Timestamp Contracts and Service Propagation

Layer / File(s) Summary
Credit purchase handler contract and validation
openmeter/billing/charges/creditpurchase/handler.go
New PaymentEventInput (Charge + EventAt); Handler payment methods now accept it and Validate requires non-zero EventAt.
Credit-purchase services
openmeter/billing/charges/creditpurchase/service/*.go, openmeter/ledger/chargeadapter/creditpurchase*.go
Compute eventAt := clock.Now() once per payment flow and reuse for handler input and settlement timed references; adapter methods accept PaymentEventInput and use EventAt for ledger At timestamps.
Flat-fee UsageBookedAt helper and handler updates
openmeter/billing/charges/flatfee/bookedat.go, openmeter/billing/charges/flatfee/handler.go
Add UsageBookedAt() helper; flat-fee handler inputs now require BookedAt/EventAt and Validate enforces non-zero timestamps.
Flat-fee services & adapters
openmeter/billing/charges/flatfee/service/*, openmeter/ledger/chargeadapter/flatfee*.go
Derive BookedAt via UsageBookedAt() and pass it to handlers; compute single eventAt for payments and use it for ledger timed refs; adapters read BookedAt/EventAt.
Usage-based handler contract updates
openmeter/billing/charges/usagebased/handler.go
Rename AllocateAtBookedAt, add EventAt on run events, and add ValidateWith(currencyCalculator) for corrections.
Usage-based services & adapters
openmeter/billing/charges/usagebased/service/*, openmeter/ledger/chargeadapter/usagebased*.go
Pass BookedAt into accrual/correction handler inputs; use EventAt for payment flows; prefer service-period-derived timestamps over clock.Now() for allocation/correction.
Test infrastructure and handler test doubles
openmeter/billing/charges/service/handlers_test.go, openmeter/billing/charges/testutils/handlers.go, many tests under openmeter/ledger/*_test.go and openmeter/billing/worker/*_test.go
Mocks and test doubles updated to accept PaymentEventInput and BookedAt; tests adjusted to freeze time where needed and assert ledger transaction BookedAt/EventAt match provided timestamps.
Integration test base & sync tests
openmeter/billing/worker/subscriptionsync/service/*
SuiteBase gains Ledger dependency and helpers to validate transaction-group BookedAt; many sync tests simulate async sync (+1m) and include BookedAt in expected realizations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • openmeterio/openmeter#4362: Flat-fee timestamp and correction input refactor that overlaps timestamp field renames and validation.

Suggested reviewers

  • tothandras
  • GAlexIHU
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix CTI ledger booking timestamps' directly maps to the main change: correcting how ledger transactions are booked at domain event times rather than derived timestamps, with specific focus on credit-then-invoice flows.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cti-booked-at-missmatches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
openmeter/billing/charges/usagebased/service/lineengine.go (1)

281-285: ⚡ Quick win

Use the run’s service-period end as the canonical correction timestamp.

Small tweak: prefer run.ServicePeriodTo over stdLine.GetServicePeriod().To here, so booking stays anchored to the persisted realization run even if line period shape drifts.

Suggested change
 		if _, err := e.service.runs.CorrectAllCredits(ctx, usagebasedrun.CorrectAllCreditRealizationsInput{
 			Charge:             charge,
 			Run:                run,
-			AllocateAt:         stdLine.GetServicePeriod().To,
+			AllocateAt:         run.ServicePeriodTo,
 			CurrencyCalculator: currencyCalculator,
 		}); err != nil {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/billing/charges/usagebased/service/lineengine.go` around lines 281
- 285, The AllocateAt timestamp passed into e.service.runs.CorrectAllCredits
should use the persisted run end instead of the line's period; replace
stdLine.GetServicePeriod().To with run.ServicePeriodTo when constructing
usagebasedrun.CorrectAllCreditRealizationsInput so the correction is anchored to
the run (update the AllocateAt field in the call to
e.service.runs.CorrectAllCredits accordingly).
openmeter/ledger/chargeadapter/creditpurchase_test.go (1)

240-254: ⚡ Quick win

Add a booked-at assertion in this back-advance settled path.

Nice that EventAt is passed here too. I’d also assert the group transactions’ BookedAt equals eventTime (same as the other settled test) so this path is protected against timestamp regressions as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/chargeadapter/creditpurchase_test.go` around lines 240 -
254, Add an assertion that the group transactions created by the settled path
have BookedAt equal to eventTime: after calling
env.handler.OnCreditPurchasePaymentSettled (where ref.TransactionGroupID is
returned and eventTime is defined), fetch the transactions for
ref.TransactionGroupID and assert each transaction.BookedAt (or the group's
BookedAt) equals eventTime to mirror the other settled test and prevent
timestamp regressions.
openmeter/ledger/chargeadapter/usagebased_test.go (1)

466-524: ⚡ Quick win

Please add a EventAt-required test for OnPaymentSettled too.

You already cover zero EventAt for authorization; adding the same negative case for settled would complete the contract checks end-to-end.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/chargeadapter/usagebased_test.go` around lines 466 - 524,
Add a negative test in TestOnUsageBasedPaymentSettled that verifies
OnPaymentSettled validates the required EventAt field: call
env.handler.OnPaymentSettled with an OnPaymentSettledInput whose EventAt is the
zero time (or omitted), assert it returns an error and that the returned
reference has an empty TransactionGroupID; place this alongside the existing
"zero invoice usage is a no-op" case to mirror the authorization test coverage
and reference the OnPaymentSettled and OnPaymentSettledInput symbols so the test
targets the same handler contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openmeter/billing/worker/subscriptionsync/service/base_test.go`:
- Around line 610-613: The test currently iterates over
actualRealization.LedgerTransactionGroups and asserts BookedAt but silently
succeeds if the slice is empty; update the test to first assert that
actualRealization.LedgerTransactionGroups is non-empty (e.g.,
require/require.NotEmpty or assert.Len>0) before entering the for-loop so the
contract is enforced, then proceed to call
s.assertLedgerTransactionGroupBookedAt(ctx, namespace, transactionGroup.ID,
expectedRealization.BookedAt, fmt.Sprintf("%s: %s", childID,
transactionGroup.Label)).

In
`@openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go`:
- Around line 893-894: The new call to clock.FreezeTime(start.Add(time.Minute))
must be paired immediately with defer clock.UnFreeze() in the same scope (or
wrapped in its own block) to avoid leaking frozen time to other tests; update
the occurrence of clock.FreezeTime(start.Add(time.Minute)) and every other
similar clock.FreezeTime(...) use noted in the review by adding a matching defer
clock.UnFreeze() (or enclosing the freeze+assertions in { ... } and deferring
UnFreeze()) so each freeze is restored before leaving that local scope.

---

Nitpick comments:
In `@openmeter/billing/charges/usagebased/service/lineengine.go`:
- Around line 281-285: The AllocateAt timestamp passed into
e.service.runs.CorrectAllCredits should use the persisted run end instead of the
line's period; replace stdLine.GetServicePeriod().To with run.ServicePeriodTo
when constructing usagebasedrun.CorrectAllCreditRealizationsInput so the
correction is anchored to the run (update the AllocateAt field in the call to
e.service.runs.CorrectAllCredits accordingly).

In `@openmeter/ledger/chargeadapter/creditpurchase_test.go`:
- Around line 240-254: Add an assertion that the group transactions created by
the settled path have BookedAt equal to eventTime: after calling
env.handler.OnCreditPurchasePaymentSettled (where ref.TransactionGroupID is
returned and eventTime is defined), fetch the transactions for
ref.TransactionGroupID and assert each transaction.BookedAt (or the group's
BookedAt) equals eventTime to mirror the other settled test and prevent
timestamp regressions.

In `@openmeter/ledger/chargeadapter/usagebased_test.go`:
- Around line 466-524: Add a negative test in TestOnUsageBasedPaymentSettled
that verifies OnPaymentSettled validates the required EventAt field: call
env.handler.OnPaymentSettled with an OnPaymentSettledInput whose EventAt is the
zero time (or omitted), assert it returns an error and that the returned
reference has an empty TransactionGroupID; place this alongside the existing
"zero invoice usage is a no-op" case to mirror the authorization test coverage
and reference the OnPaymentSettled and OnPaymentSettledInput symbols so the test
targets the same handler contract.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 83e9f057-3633-430e-bdf8-e73222a2d9da

📥 Commits

Reviewing files that changed from the base of the PR and between 9700167 and c557e9e.

📒 Files selected for processing (35)
  • openmeter/billing/charges/creditpurchase/handler.go
  • openmeter/billing/charges/creditpurchase/service/external.go
  • openmeter/billing/charges/creditpurchase/service/invoice.go
  • openmeter/billing/charges/flatfee/bookedat.go
  • openmeter/billing/charges/flatfee/handler.go
  • openmeter/billing/charges/flatfee/service/creditheninvoice.go
  • openmeter/billing/charges/flatfee/service/creditsonly.go
  • openmeter/billing/charges/flatfee/service/lineengine.go
  • openmeter/billing/charges/flatfee/service/payment.go
  • openmeter/billing/charges/flatfee/service/realizations/correct.go
  • openmeter/billing/charges/flatfee/service/realizations/creditsonly.go
  • openmeter/billing/charges/flatfee/service/realizations/credittheninvoice.go
  • openmeter/billing/charges/flatfee/service/realizations/invoiceaccrued.go
  • openmeter/billing/charges/service/creditpurchase_test.go
  • openmeter/billing/charges/service/handlers_test.go
  • openmeter/billing/charges/service/invoicable_test.go
  • openmeter/billing/charges/service/taxcode_test.go
  • openmeter/billing/charges/testutils/handlers.go
  • openmeter/billing/charges/usagebased/handler.go
  • openmeter/billing/charges/usagebased/service/creditheninvoice.go
  • openmeter/billing/charges/usagebased/service/creditsonly.go
  • openmeter/billing/charges/usagebased/service/lineengine.go
  • openmeter/billing/charges/usagebased/service/run/correct.go
  • openmeter/billing/charges/usagebased/service/run/create.go
  • openmeter/billing/charges/usagebased/service/run/credits.go
  • openmeter/billing/charges/usagebased/service/run/invoice.go
  • openmeter/billing/charges/usagebased/service/run/payment.go
  • openmeter/billing/worker/subscriptionsync/service/base_test.go
  • openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go
  • openmeter/ledger/chargeadapter/creditpurchase.go
  • openmeter/ledger/chargeadapter/creditpurchase_test.go
  • openmeter/ledger/chargeadapter/flatfee.go
  • openmeter/ledger/chargeadapter/flatfee_test.go
  • openmeter/ledger/chargeadapter/usagebased.go
  • openmeter/ledger/chargeadapter/usagebased_test.go

Comment thread openmeter/billing/worker/subscriptionsync/service/base_test.go
@turip turip force-pushed the fix/cti-booked-at-missmatches branch from c557e9e to c5827bf Compare May 20, 2026 11:13
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
openmeter/billing/worker/subscriptionsync/service/base_test.go (1)

605-613: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Assert realization ledger groups are non-empty before checking BookedAt.

Right now the loop can silently pass when there are no realization ledger groups, so this assertion doesn’t fully enforce the timestamp contract.

Suggested patch
 func (s *SuiteBase) assertChargeRealizationLedgerTransactions(ctx context.Context, namespace string, childID string, expectedRealization expectedChargeRealization, actualRealization actualChargeRealization) {
 	s.T().Helper()

 	s.Require().False(expectedRealization.BookedAt.IsZero(), "%s: realization booked_at", childID)
+	s.Require().NotEmpty(actualRealization.LedgerTransactionGroups, "%s: realization ledger transaction groups", childID)

 	for _, transactionGroup := range actualRealization.LedgerTransactionGroups {
 		s.assertLedgerTransactionGroupBookedAt(ctx, namespace, transactionGroup.ID, expectedRealization.BookedAt, fmt.Sprintf("%s: %s", childID, transactionGroup.Label))
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/billing/worker/subscriptionsync/service/base_test.go` around lines
605 - 613, The test helper assertChargeRealizationLedgerTransactions currently
iterates actualRealization.LedgerTransactionGroups without asserting it contains
entries, so add a precondition check that
actualRealization.LedgerTransactionGroups is non-empty (e.g.
s.Require().NotEmpty or s.Require().Greater(len(...), 0)) before the for loop to
ensure the BookedAt timestamp contract is enforced; keep the existing check of
expectedRealization.BookedAt.IsZero and call
assertLedgerTransactionGroupBookedAt for each group as before, using the same
childID/context in the error message.
🧹 Nitpick comments (1)
openmeter/ledger/chargeadapter/usagebased_test.go (1)

466-524: ⚡ Quick win

Missing "event at is required" validation test for OnPaymentSettled.

TestOnUsageBasedPaymentAuthorized has an "event at is required" test, but TestOnUsageBasedPaymentSettled doesn't have a matching validation test. Worth adding for consistency and to ensure the input validation is covered.

🧪 Suggested test case to add
 	t.Run("zero invoice usage is a no-op", func(t *testing.T) {
 		env := newUsageBasedHandlerTestEnv(t)

 		ref, err := env.handler.OnPaymentSettled(t.Context(), chargeusagebased.OnPaymentSettledInput{
 			Charge:  env.newCharge(productcatalog.CreditThenInvoiceSettlementMode),
 			Run:     env.newRunWithAuthorizedPaymentAndInvoiceUsage("line-1", alpacadecimal.NewFromInt(1), alpacadecimal.Zero),
 			EventAt: env.Now(),
 		})
 		require.NoError(t, err)
 		require.Empty(t, ref.TransactionGroupID)
 	})
+
+	t.Run("event at is required", func(t *testing.T) {
+		env := newUsageBasedHandlerTestEnv(t)
+
+		ref, err := env.handler.OnPaymentSettled(t.Context(), chargeusagebased.OnPaymentSettledInput{
+			Charge:  env.newCharge(productcatalog.CreditThenInvoiceSettlementMode),
+			Run:     env.newRunWithAuthorizedPayment("line-1", alpacadecimal.NewFromInt(10)),
+			EventAt: time.Time{},
+		})
+		require.ErrorContains(t, err, "event at is required")
+		require.Empty(t, ref.TransactionGroupID)
+	})
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openmeter/ledger/chargeadapter/usagebased_test.go` around lines 466 - 524,
Add a subtest to TestOnUsageBasedPaymentSettled that verifies input validation
rejects a missing EventAt: create env := newUsageBasedHandlerTestEnv(t), call
env.handler.OnPaymentSettled with a valid Charge and Run but EventAt set to
time.Time{} (zero value), then assert the call returns an error and that the
error message contains/indicates "event at is required"; reference the
TestOnUsageBasedPaymentSettled test and the handler.OnPaymentSettled method for
where to add this check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@openmeter/billing/worker/subscriptionsync/service/base_test.go`:
- Around line 605-613: The test helper assertChargeRealizationLedgerTransactions
currently iterates actualRealization.LedgerTransactionGroups without asserting
it contains entries, so add a precondition check that
actualRealization.LedgerTransactionGroups is non-empty (e.g.
s.Require().NotEmpty or s.Require().Greater(len(...), 0)) before the for loop to
ensure the BookedAt timestamp contract is enforced; keep the existing check of
expectedRealization.BookedAt.IsZero and call
assertLedgerTransactionGroupBookedAt for each group as before, using the same
childID/context in the error message.

---

Nitpick comments:
In `@openmeter/ledger/chargeadapter/usagebased_test.go`:
- Around line 466-524: Add a subtest to TestOnUsageBasedPaymentSettled that
verifies input validation rejects a missing EventAt: create env :=
newUsageBasedHandlerTestEnv(t), call env.handler.OnPaymentSettled with a valid
Charge and Run but EventAt set to time.Time{} (zero value), then assert the call
returns an error and that the error message contains/indicates "event at is
required"; reference the TestOnUsageBasedPaymentSettled test and the
handler.OnPaymentSettled method for where to add this check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dce89e23-3536-4f3d-b30e-b768e2fe7cef

📥 Commits

Reviewing files that changed from the base of the PR and between c557e9e and c5827bf.

📒 Files selected for processing (35)
  • openmeter/billing/charges/creditpurchase/handler.go
  • openmeter/billing/charges/creditpurchase/service/external.go
  • openmeter/billing/charges/creditpurchase/service/invoice.go
  • openmeter/billing/charges/flatfee/bookedat.go
  • openmeter/billing/charges/flatfee/handler.go
  • openmeter/billing/charges/flatfee/service/creditheninvoice.go
  • openmeter/billing/charges/flatfee/service/creditsonly.go
  • openmeter/billing/charges/flatfee/service/lineengine.go
  • openmeter/billing/charges/flatfee/service/payment.go
  • openmeter/billing/charges/flatfee/service/realizations/correct.go
  • openmeter/billing/charges/flatfee/service/realizations/creditsonly.go
  • openmeter/billing/charges/flatfee/service/realizations/credittheninvoice.go
  • openmeter/billing/charges/flatfee/service/realizations/invoiceaccrued.go
  • openmeter/billing/charges/service/creditpurchase_test.go
  • openmeter/billing/charges/service/handlers_test.go
  • openmeter/billing/charges/service/invoicable_test.go
  • openmeter/billing/charges/service/taxcode_test.go
  • openmeter/billing/charges/testutils/handlers.go
  • openmeter/billing/charges/usagebased/handler.go
  • openmeter/billing/charges/usagebased/service/creditheninvoice.go
  • openmeter/billing/charges/usagebased/service/creditsonly.go
  • openmeter/billing/charges/usagebased/service/lineengine.go
  • openmeter/billing/charges/usagebased/service/run/correct.go
  • openmeter/billing/charges/usagebased/service/run/create.go
  • openmeter/billing/charges/usagebased/service/run/credits.go
  • openmeter/billing/charges/usagebased/service/run/invoice.go
  • openmeter/billing/charges/usagebased/service/run/payment.go
  • openmeter/billing/worker/subscriptionsync/service/base_test.go
  • openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go
  • openmeter/ledger/chargeadapter/creditpurchase.go
  • openmeter/ledger/chargeadapter/creditpurchase_test.go
  • openmeter/ledger/chargeadapter/flatfee.go
  • openmeter/ledger/chargeadapter/flatfee_test.go
  • openmeter/ledger/chargeadapter/usagebased.go
  • openmeter/ledger/chargeadapter/usagebased_test.go

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openmeter/ledger/chargeadapter/bookedat_test.go`:
- Around line 13-19: Both helpers (requireLedgerBookedAtEqual and
requireLedgerBookedAtNotEqual) only truncate expected to microseconds, so
normalize both timestamps before comparing: convert actual and expected to UTC
and call Truncate(time.Microsecond) on each, then use Equal in
require.True/require.False; update the comparison expressions in both helper
functions (referencing requireLedgerBookedAtEqual and
requireLedgerBookedAtNotEqual) accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c156ebc2-7ed5-4017-af03-a3769d6eda44

📥 Commits

Reviewing files that changed from the base of the PR and between 1f7bcf8 and 62d36a8.

📒 Files selected for processing (5)
  • openmeter/ledger/chargeadapter/bookedat_test.go
  • openmeter/ledger/chargeadapter/creditpurchase_test.go
  • openmeter/ledger/chargeadapter/flatfee_test.go
  • openmeter/ledger/chargeadapter/usagebased_test.go
  • openmeter/ledger/customerbalance/expired_loader_test.go

Comment thread openmeter/ledger/chargeadapter/bookedat_test.go Outdated
@turip turip added release-note/bug-fix Release note: Bug Fixes area/billing labels May 20, 2026
@turip turip merged commit 470f7dd into main May 21, 2026
28 checks passed
@turip turip deleted the fix/cti-booked-at-missmatches branch May 21, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants