Skip to content

feat(api): add charges list api http handler#4103

Merged
turip merged 9 commits intomainfrom
feat/add-charges-list-api-http-handler
Apr 16, 2026
Merged

feat(api): add charges list api http handler#4103
turip merged 9 commits intomainfrom
feat/add-charges-list-api-http-handler

Conversation

@mark-vass-konghq
Copy link
Copy Markdown
Contributor

@mark-vass-konghq mark-vass-konghq commented Apr 8, 2026

@coderabbitai

Summary by CodeRabbit

  • New Features
    • Added "List Customer Charges" API: paginated results, status filtering (with validation), optional real-time usage expansion, and detailed charge payloads for flat-fee and usage-based charges (pricing, discounts, totals, periods, references, and timestamps).
  • Integration
    • Server and router wiring updated to enable charges functionality when a charges service is provided; preserves prior behavior when not configured.
  • Tests
    • Added route tests and a no-op test service to validate enabled vs. not-configured behaviors.

@mark-vass-konghq mark-vass-konghq self-assigned this Apr 8, 2026
@mark-vass-konghq mark-vass-konghq requested a review from a team as a code owner April 8, 2026 12:40
@mark-vass-konghq mark-vass-konghq added the release-note/feature Release note: Exciting New Features label Apr 8, 2026
@mark-vass-konghq mark-vass-konghq force-pushed the feat/add-charges-list-api-http-handler branch from b4a50fa to 3ed7395 Compare April 8, 2026 12:40
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 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
📝 Walkthrough

Walkthrough

Adds a new charges handler and ListCustomerCharges endpoint, conversion utilities mapping billing charge domain models into v3 API union types, wires a ChargeService through router/server/CLI, and adds tests including a NoopChargeService and route assertions.

Changes

Cohort / File(s) Summary
API handler & conversion
api/v3/handlers/charges/handler.go, api/v3/handlers/charges/list.go, api/v3/handlers/charges/convert.go, api/v3/handlers/charges/convert.gen.go
New Handler interface and constructor; implemented ListCustomerCharges HTTP handler (namespace resolution, pagination defaults/validation, status filter parsing/complementing, expansion mapping) and conversion logic for FlatFee and UsageBased billing charges (union discrimination, discount mapping, totals placeholder). Added helpers for metadata→labels, enums, currency/amount, subscription refs, and time-pointer handling.
Server & routing wiring
api/v3/server/server.go, api/v3/server/routes.go
Added ChargeService to v3 server Config, added chargesHandler to Server, and route now delegates to chargesHandler.ListCustomerCharges() when configured, otherwise falls back to the prior unimplemented handler.
Application router & CLI
openmeter/server/router/router.go, openmeter/server/server.go, cmd/server/main.go
Exposed ChargeService on router Config and forwarded it into v3 server config; CLI now supplies ChargeService from the app billing registry. Router Config.Validate() not changed.
Tests
openmeter/server/server_test.go
Test harness now accepts router config overrides; added TestListCustomerChargesRoute asserting 200 with configured ChargeService; added NoopChargeService test double; updated route table to expect 501 when ChargeService is absent.

Sequence Diagram

sequenceDiagram
    actor Client
    participant Handler
    participant ChargeService
    participant Converter

    Client->>Handler: GET /api/v3/.../customers/{id}/charges
    Handler->>Handler: parse & validate query params
    Handler->>Handler: resolve namespace
    Handler->>Handler: parse status filter & compute complement
    Handler->>ChargeService: ListCharges(ctx, filters, pagination)
    ChargeService-->>Handler: charges + total count
    loop per charge
        Handler->>Converter: convertChargeToAPI(charge)
        Converter-->>Handler: api.BillingCharge
    end
    Handler-->>Client: 200 JSON PagePaginationResponse[api.BillingCharge]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Possibly related PRs

Suggested labels

area/api, area/billing

Suggested reviewers

  • tothandras
  • turip
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main change: introducing a new HTTP handler for listing charges in the API layer.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-charges-list-api-http-handler

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: 1

🧹 Nitpick comments (2)
openmeter/server/server_test.go (1)

603-613: Please cover at least one non-empty charges page.

Between the 501 case and the empty-page NoopChargeService, these tests only prove the routing. None of the new flat-fee / usage-based conversion logic gets exercised, so response-shape bugs can slip through pretty easily.

As per coding guidelines **/*_test.go: Make sure the tests are comprehensive and cover the changes. Keep a strong focus on unit tests and in-code integration tests.

Also applies to: 790-809, 838-843

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@openmeter/server/server_test.go` around lines 603 - 613, Add at least one
test case that returns a non-empty charges page to exercise the conversion logic
(flat-fee and usage-based) rather than only routing; create a testRequest to GET
"/api/v3/openmeter/customers/01ARZ3NDEKTSV4RRFFQ69G5FAV/charges" but configure
the test server to use a real/mock ChargeService (not NoopChargeService) that
returns a page with at least one Charge containing both flat-fee and usage-based
entries, then assert the testResponse body and status (instead of only expecting
http.StatusNotImplemented) to validate the response shape and conversion
behavior handled by the charges handler (the code that reads
testRequest/testResponse and invokes the charges endpoint).
api/v3/handlers/charges/list.go (1)

138-160: Consider deriving statuses from Values() to stay in sync with the enum.

The hardcoded list mirrors meta.ChargeStatus values, but if a new status is added to the enum later, this list could get out of sync silently. When that happens, the complement calculation would be incorrect - users could see charges with unexpected statuses.

You could derive this dynamically from the Values() method:

♻️ Suggested refactor to use Values()
 // chargeStatusComplement returns all valid statuses not in the given set.
 func chargeStatusComplement(include []meta.ChargeStatus) []meta.ChargeStatus {
-	all := []meta.ChargeStatus{
-		meta.ChargeStatusCreated,
-		meta.ChargeStatusActive,
-		meta.ChargeStatusFinal,
-		meta.ChargeStatusDeleted,
-	}
+	// Derive all valid statuses from the enum's Values() method
+	// to stay in sync if new statuses are added.
+	allStrings := meta.ChargeStatus("").Values()
+	all := make([]meta.ChargeStatus, len(allStrings))
+	for i, s := range allStrings {
+		all[i] = meta.ChargeStatus(s)
+	}

 	includeSet := make(map[meta.ChargeStatus]bool, len(include))
 	for _, s := range include {
 		includeSet[s] = true
 	}

 	var complement []meta.ChargeStatus
 	for _, s := range all {
 		if !includeSet[s] {
 			complement = append(complement, s)
 		}
 	}

 	return complement
 }

Alternatively, at minimum a comment noting the coupling would help future maintainers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/list.go` around lines 138 - 160, The hardcoded list
in chargeStatusComplement is coupled to the enum; replace the manual all :=
[...] slice with a dynamic slice derived from the enum's Values() helper (e.g.
call meta.ChargeStatus.Values() or the package's equivalent that returns
[]meta.ChargeStatus) so new statuses are automatically included, then keep the
existing includeSet/complement logic unchanged; if no Values() exists, add a
clear comment explaining the coupling and a TODO to switch to the enum Values()
when available.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@api/v3/handlers/charges/convert.go`:
- Around line 39-49: The handler currently lets meta.ChargeTypeCreditPurchase
through so convertChargeToAPI crashes; either fix the handler by populating the
ListChargesInput.ChargeTypes to exclude meta.ChargeTypeCreditPurchase when
building the query (so the adapter never returns credit-purchase rows), or make
convertChargeToAPI skip credit purchases instead of erroring by detecting
meta.ChargeTypeCreditPurchase (the switch case using
charge.AsCreditPurchaseCharge()) and returning a skip signal (e.g., nil/zero
value or a boolean) that the caller will ignore; update the caller code to
handle that skip signal if you choose the converter-change route.

---

Nitpick comments:
In `@api/v3/handlers/charges/list.go`:
- Around line 138-160: The hardcoded list in chargeStatusComplement is coupled
to the enum; replace the manual all := [...] slice with a dynamic slice derived
from the enum's Values() helper (e.g. call meta.ChargeStatus.Values() or the
package's equivalent that returns []meta.ChargeStatus) so new statuses are
automatically included, then keep the existing includeSet/complement logic
unchanged; if no Values() exists, add a clear comment explaining the coupling
and a TODO to switch to the enum Values() when available.

In `@openmeter/server/server_test.go`:
- Around line 603-613: Add at least one test case that returns a non-empty
charges page to exercise the conversion logic (flat-fee and usage-based) rather
than only routing; create a testRequest to GET
"/api/v3/openmeter/customers/01ARZ3NDEKTSV4RRFFQ69G5FAV/charges" but configure
the test server to use a real/mock ChargeService (not NoopChargeService) that
returns a page with at least one Charge containing both flat-fee and usage-based
entries, then assert the testResponse body and status (instead of only expecting
http.StatusNotImplemented) to validate the response shape and conversion
behavior handled by the charges handler (the code that reads
testRequest/testResponse and invokes the charges endpoint).
🪄 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: e596a720-200c-4d29-a227-79924d220e0e

📥 Commits

Reviewing files that changed from the base of the PR and between 19889fb and 3ed7395.

📒 Files selected for processing (9)
  • api/v3/handlers/charges/convert.go
  • api/v3/handlers/charges/handler.go
  • api/v3/handlers/charges/list.go
  • api/v3/server/routes.go
  • api/v3/server/server.go
  • cmd/server/main.go
  • openmeter/server/router/router.go
  • openmeter/server/server.go
  • openmeter/server/server_test.go

Comment thread api/v3/handlers/customers/charges/convert.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.

🧹 Nitpick comments (3)
api/v3/handlers/charges/convert.go (2)

220-226: Consider returning nil when metadata is empty.

The function always returns a non-nil *api.Labels, even when source is empty. If the API expects labels to be omitted when there are none (based on omitempty in the JSON tag), this could result in an empty object {} in the response instead of the field being absent.

✨ Optional fix
 func convertMetadataToLabels(source models.Metadata) *api.Labels {
+	if len(source) == 0 {
+		return nil
+	}
 	labels := make(api.Labels)
 	for k, v := range source {
 		labels[k] = v
 	}
 	return &labels
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/convert.go` around lines 220 - 226, The
convertMetadataToLabels function always returns a non-nil *api.Labels even for
empty input; change it to return nil when the incoming models.Metadata is nil or
has zero entries so the JSON omitempty can omit the field. Locate
convertMetadataToLabels and add a guard that checks len(source) == 0 (or source
== nil) and returns nil; otherwise build and return the populated *api.Labels as
before. Ensure callers that receive the result can handle a nil *api.Labels
appropriately.

162-174: TODO: Implement proper totals aggregation.

Just flagging this for visibility—the convertUsageBasedChargeTotals function returns zero values for all totals. The comment indicates this is intentional for now, but make sure to track this as a follow-up.

Would you like me to open an issue to track this implementation?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/convert.go` around lines 162 - 174, The
convertUsageBasedChargeTotals function currently returns hard-coded zero totals;
replace the TODO by aggregating actual totals from the usagebased.Charge (e.g.,
iterate ch.Realizations or equivalent field on usagebased.Charge), summing
numeric fields into an api.BillingTotals value and returning that inside
api.BillingChargeTotals.Booked. Ensure you parse/accumulate amounts using a
precise decimal type (not float64) and format the final summed values as strings
to match api.BillingTotals (Amount, ChargesTotal, CreditsTotal, DiscountsTotal,
TaxesExclusiveTotal); update any helper functions or add a small aggregator
inside convertUsageBasedChargeTotals to perform the sums safely.
api/v3/handlers/charges/list.go (1)

138-160: Consider moving the status list to a canonical method in the meta package.

The status list in chargeStatusComplement mirrors the constants defined in meta.ChargeStatus (in meta/charge.go). While the Values() method returns string representations, it'd be cleaner to add a dedicated Statuses() or All() method to the meta package that returns []meta.ChargeStatus directly. Then the handler can call that instead of maintaining a separate list.

This prevents accidental drift if someone adds a new status to the constants but forgets to update the handler.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/list.go` around lines 138 - 160, The handler's
chargeStatusComplement currently hardcodes the list of statuses; add a canonical
accessor in the meta package (e.g., a function like meta.AllChargeStatuses() or
meta.ChargeStatusValues() that returns []meta.ChargeStatus) and update
chargeStatusComplement to call that instead of the local all slice; modify or
add the new function in the meta package near the ChargeStatus definitions and
replace the inline list in chargeStatusComplement with a call to the new meta
method so the source of truth for statuses lives in meta.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/v3/handlers/charges/convert.go`:
- Around line 220-226: The convertMetadataToLabels function always returns a
non-nil *api.Labels even for empty input; change it to return nil when the
incoming models.Metadata is nil or has zero entries so the JSON omitempty can
omit the field. Locate convertMetadataToLabels and add a guard that checks
len(source) == 0 (or source == nil) and returns nil; otherwise build and return
the populated *api.Labels as before. Ensure callers that receive the result can
handle a nil *api.Labels appropriately.
- Around line 162-174: The convertUsageBasedChargeTotals function currently
returns hard-coded zero totals; replace the TODO by aggregating actual totals
from the usagebased.Charge (e.g., iterate ch.Realizations or equivalent field on
usagebased.Charge), summing numeric fields into an api.BillingTotals value and
returning that inside api.BillingChargeTotals.Booked. Ensure you
parse/accumulate amounts using a precise decimal type (not float64) and format
the final summed values as strings to match api.BillingTotals (Amount,
ChargesTotal, CreditsTotal, DiscountsTotal, TaxesExclusiveTotal); update any
helper functions or add a small aggregator inside convertUsageBasedChargeTotals
to perform the sums safely.

In `@api/v3/handlers/charges/list.go`:
- Around line 138-160: The handler's chargeStatusComplement currently hardcodes
the list of statuses; add a canonical accessor in the meta package (e.g., a
function like meta.AllChargeStatuses() or meta.ChargeStatusValues() that returns
[]meta.ChargeStatus) and update chargeStatusComplement to call that instead of
the local all slice; modify or add the new function in the meta package near the
ChargeStatus definitions and replace the inline list in chargeStatusComplement
with a call to the new meta method so the source of truth for statuses lives in
meta.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 87aed2e1-1c3a-4273-a5bc-d3c63c1704d2

📥 Commits

Reviewing files that changed from the base of the PR and between 3ed7395 and 92a9bdc.

📒 Files selected for processing (9)
  • api/v3/handlers/charges/convert.go
  • api/v3/handlers/charges/handler.go
  • api/v3/handlers/charges/list.go
  • api/v3/server/routes.go
  • api/v3/server/server.go
  • cmd/server/main.go
  • openmeter/server/router/router.go
  • openmeter/server/server.go
  • openmeter/server/server_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • openmeter/server/server.go
  • openmeter/server/router/router.go
  • cmd/server/main.go
  • api/v3/server/routes.go
  • api/v3/handlers/charges/handler.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 the current code and only fix it if needed.

Inline comments:
In `@api/v3/handlers/charges/list.go`:
- Around line 124-138: parseChargeStatusFilter currently treats an empty oeq
string as a single empty part which triggers validation errors; add an early
guard in parseChargeStatusFilter to treat an empty or all-whitespace oeq as no
filters and return an empty []meta.ChargeStatus and nil error. Check
strings.TrimSpace(oeq) at the top of the function and return the empty slice
immediately before calling strings.Split or creating meta.ChargeStatus values so
validation isn't invoked on an empty string.
🪄 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: 9ced6ed0-3532-40a5-88a2-2f0688db442d

📥 Commits

Reviewing files that changed from the base of the PR and between 92a9bdc and ff54786.

📒 Files selected for processing (2)
  • api/v3/handlers/charges/convert.go
  • api/v3/handlers/charges/list.go

Comment thread api/v3/handlers/customers/charges/list.go Outdated
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.

🧹 Nitpick comments (1)
api/v3/handlers/charges/list.go (1)

84-89: Consider deduplicating expand values before appending.

If clients send repeated expand values, req.Expands can contain duplicates. Tiny thing, but this endpoint is on a DB-backed list path, so trimming redundant flags helps keep downstream work predictable.

♻️ Suggested tweak
 			// Parse expand
 			if args.Params.Expand != nil {
 				for _, exp := range *args.Params.Expand {
 					if exp == api.BillingChargesExpandRealTimeUsage {
-						req.Expands = append(req.Expands, meta.ExpandRealizations)
+						req.Expands = append(req.Expands, meta.ExpandRealizations)
+						break // prevent duplicate realizations expand
 					}
 				}
 			}

As per coding guidelines: “Performance should be a priority in critical code paths… database operations … should be vetted for potential performance bottlenecks.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/list.go` around lines 84 - 89, Deduplicate expand
values before appending to req.Expands: when handling args.Params.Expand in the
handler (the loop that checks for api.BillingChargesExpandRealTimeUsage), track
already-added expands (e.g., a local set keyed by meta.ExpandRealizations or
existing entries in req.Expands) and only append meta.ExpandRealizations if it
isn't already present; update the logic around args.Params.Expand,
api.BillingChargesExpandRealTimeUsage, req.Expands and meta.ExpandRealizations
to perform this existence check to avoid duplicates.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/v3/handlers/charges/list.go`:
- Around line 84-89: Deduplicate expand values before appending to req.Expands:
when handling args.Params.Expand in the handler (the loop that checks for
api.BillingChargesExpandRealTimeUsage), track already-added expands (e.g., a
local set keyed by meta.ExpandRealizations or existing entries in req.Expands)
and only append meta.ExpandRealizations if it isn't already present; update the
logic around args.Params.Expand, api.BillingChargesExpandRealTimeUsage,
req.Expands and meta.ExpandRealizations to perform this existence check to avoid
duplicates.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67b92011-7dd3-42cf-b7db-1ffec6ac629d

📥 Commits

Reviewing files that changed from the base of the PR and between ff54786 and fae83eb.

📒 Files selected for processing (1)
  • api/v3/handlers/charges/list.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.

🧹 Nitpick comments (1)
api/v3/handlers/charges/convert.go (1)

141-172: Placeholder values for Price and Totals.

The Price is hardcoded to "0" and convertUsageBasedChargeTotals returns zeroed totals. Both have TODO comments acknowledging they need proper implementation. If this is intentional for an MVP/incremental release, that's fine - just wanted to call it out in case you'd like help mapping the productcatalog.Price type or aggregating realization runs.

Would you like me to help draft the implementation for either of these TODOs, or open tracking issues for them?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/v3/handlers/charges/convert.go` around lines 141 - 172, Replace the
placeholder apiUB.Price = api.CurrencyAmount{Amount: "0"} with a proper mapping
from the productcatalog.Price value on the usage-based intent (e.g., implement
and call a helper like mapProductPriceToCurrencyAmount(productcatalog.Price) to
populate api.CurrencyAmount fields). Implement
convertUsageBasedChargeTotals(usagebased.Charge) to aggregate booked and
realtime totals by iterating the realization runs on the provided
usagebased.Charge (sum amounts into Booked and Realtime api.BillingTotals
fields: Amount, ChargesTotal, CreditsTotal, DiscountsTotal,
TaxesExclusiveTotal), and return those totals in api.BillingChargeTotals; use
clear helper names (e.g., sumRealizationsToBillingTotals) and reference the
usagebased.Charge’s realizations/intent fields when computing the sums. Ensure
the new helpers are used where apiUB.Price and convertUsageBasedChargeTotals are
currently invoked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/v3/handlers/charges/convert.go`:
- Around line 141-172: Replace the placeholder apiUB.Price =
api.CurrencyAmount{Amount: "0"} with a proper mapping from the
productcatalog.Price value on the usage-based intent (e.g., implement and call a
helper like mapProductPriceToCurrencyAmount(productcatalog.Price) to populate
api.CurrencyAmount fields). Implement
convertUsageBasedChargeTotals(usagebased.Charge) to aggregate booked and
realtime totals by iterating the realization runs on the provided
usagebased.Charge (sum amounts into Booked and Realtime api.BillingTotals
fields: Amount, ChargesTotal, CreditsTotal, DiscountsTotal,
TaxesExclusiveTotal), and return those totals in api.BillingChargeTotals; use
clear helper names (e.g., sumRealizationsToBillingTotals) and reference the
usagebased.Charge’s realizations/intent fields when computing the sums. Ensure
the new helpers are used where apiUB.Price and convertUsageBasedChargeTotals are
currently invoked.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: af2095e1-c589-4e63-909b-13bff9db29cd

📥 Commits

Reviewing files that changed from the base of the PR and between fae83eb and 6d33fd9.

📒 Files selected for processing (3)
  • api/v3/handlers/charges/convert.gen.go
  • api/v3/handlers/charges/convert.go
  • api/v3/handlers/charges/list.go

Comment thread api/v3/handlers/charges/convert.go Outdated
Comment thread api/v3/handlers/customers/charges/list.go Outdated
Comment thread openmeter/billing/charges/service/get.go Outdated
turip
turip previously approved these changes Apr 16, 2026
@turip turip merged commit 7b40d30 into main Apr 16, 2026
24 checks passed
@turip turip deleted the feat/add-charges-list-api-http-handler branch April 16, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/feature Release note: Exciting New Features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants