Skip to content

feat: add filter and sort to billing profile#4377

Open
borosr wants to merge 3 commits into
mainfrom
feat/billing-v3-api-filters
Open

feat: add filter and sort to billing profile#4377
borosr wants to merge 3 commits into
mainfrom
feat/billing-v3-api-filters

Conversation

@borosr

@borosr borosr commented May 18, 2026

Copy link
Copy Markdown
Contributor

Add filters and sorting to the List App endpoint

What

Adds filter[*] query parameters and a sort query parameter to GET /api/v3/openmeter/apps.

Supported filters: id, name.

Supported sort fields: id, name, createdAt (default), updatedAt with optional asc/desc suffix.

Why

Callers need a way to narrow down billing profile results without client-side filtering, e.g. finding all billing profiles for a given type or sorted by creation time.

How

  • Create the TypeSpec model with ListBillingProfilesParamsFilter and wired sort/filter query params into list
  • Regenerated OpenAPI spec and Go server bindings
  • Updated the HTTP handler to parse and validate filter/sort params, then pass them into ListBillingProfilesRequest
  • Propagated the new fields through the service and adapter layers

Testing

Filter by billing profile name:

curl -s "http://localhost:8888/api/v3/openmeter/profiles?sort=createdAt%20asc&filter%5Bname%5D%5Bcontains%5D=sandbox"

Sort by creation date descending:

curl -s  "http://localhost:8888/api/v3/openmeter/profiles?sort=createdAt%20asc"

Summary by CodeRabbit

  • New Features
    • Added filtering (by ID and name) and sorting to the billing profiles list endpoint.
  • Bug Fixes
    • Invalid sort or filter inputs now return clear 400 Bad Request responses tied to the specific query parameter.
  • Client
    • JavaScript client and schemas updated to accept the new filter and sort query parameters.
  • Tests
    • Added tests covering filtering, sorting, validation, and error cases for billing profiles listing.

@borosr borosr requested a review from tothandras May 18, 2026 13:58
@borosr borosr self-assigned this May 18, 2026
@borosr borosr requested a review from a team as a code owner May 18, 2026 13:58
@borosr borosr added the release-note/ignore Ignore this change when generating release notes label May 18, 2026
@borosr borosr force-pushed the feat/billing-v3-api-filters branch from 588e62e to 962d629 Compare May 18, 2026 13:59
@coderabbitai

coderabbitai Bot commented May 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: c20310d0-cb4e-4c7c-bff7-0adb79af677c

📥 Commits

Reviewing files that changed from the base of the PR and between 9ee3534 and 448689c.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (9)
  • api/spec/packages/aip-client-javascript/src/funcs/billing.ts
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip-client-javascript/src/models/operations/billing.ts
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts
  • api/spec/packages/aip/src/billing/operations.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billingprofiles/list.go
  • openmeter/billing/adapter/profile.go
💤 Files with no reviewable changes (3)
  • api/spec/packages/aip-client-javascript/src/models/schemas.ts
  • api/spec/packages/aip-client-javascript/src/models/types.ts
  • api/v3/api.gen.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/v3/handlers/billingprofiles/list.go
  • openmeter/billing/adapter/profile.go
  • api/spec/packages/aip/src/billing/operations.tsp

📝 Walkthrough

Walkthrough

This PR adds deep-object filter (id, name) and sort query support to billing profiles listing: API spec and generated bindings, handler parsing with parameter-scoped validation, domain OrderBy and filter types/validation, adapter query application, HTTP driver mapping, client SDK types/schemas, and service tests.

Changes

Billing profiles filtering and sorting

Layer / File(s) Summary
OrderBy type and ListProfilesInput contract
openmeter/billing/profile.go
Adds exported OrderBy type and OrderBy* constants, imports pkg/filter, adds ID *filter.FilterULID and Name *filter.FilterString to ListProfilesInput, and updates Validate() to validate optional filters and order-by.
API specification & generated server bindings
api/spec/packages/aip/src/billing/operations.tsp, api/v3/api.gen.go
Adds ListBillingProfilesParamsFilter (id, name), extends the list operation with sort?: Common.SortQuery and deep-object filter?: ListBillingProfilesParamsFilter, updates generated ListBillingProfilesParams and server wrapper binding, and refreshes embedded swagger spec.
HTTP handler query parameter parsing
api/v3/handlers/billingprofiles/list.go
Imports api/v3/filters and api/v3/request, parses params.Sort and params.Filter, maps parsed values into request OrderBy/Order and ID/Name, and returns parameter-scoped 400 errors on invalid input.
HTTP driver parameter mapping
openmeter/billing/httpdriver/profile.go
Casts optional API params.OrderBy into billing.OrderBy(...) when building the request; preserves existing default when nil.
Adapter query construction
openmeter/billing/adapter/profile.go
Removes api import, adds pkg/filter import, applies filter.ApplyToQuery for optional ID and Name, and switches ordering logic to use billing.OrderBy* constants to set Ent ordering.
Client JS types & schemas
api/spec/packages/aip-client-javascript/src/*
Re-exports new ListBillingProfilesParamsFilter, extends ListBillingProfilesQuery with sort and filter, adds listBillingProfilesParamsFilter Zod schema, and includes sort/filter in listBillingProfiles request construction.
Service behavior tests
openmeter/billing/service/profile_test.go
Adds recordingAdapter, newServiceForProfileTest, and table-driven TestListProfiles cases asserting filter operator mapping, ID/name mapping, sort mapping, and validation error on conflicting operators.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

area/api, area/billing, release-note/feature

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 clearly and concisely summarizes the main change: adding filter and sort capabilities to the billing profile listing endpoint.
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 feat/billing-v3-api-filters

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openmeter/billing/profile.go (1)

409-437: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Collect namespace/expand errors into errs too for Validate() consistency.

This method now aggregates some errors, but Line 410 and Line 414 still return early. To match project validation behavior, collect all field errors and return a single joined validation error.

As per coding guidelines, openmeter/**/*.go: “For Validate() error methods, collect all validation issues into var errs []error and return models.NewNillableGenericValidationError(errors.Join(errs...)) instead of returning on the first invalid field”.

🤖 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/profile.go` around lines 409 - 437,
ListProfilesInput.Validate currently returns early for Namespace and Expand
errors instead of collecting them; update the method
(ListProfilesInput.Validate) to append validation errors for Namespace and for
i.Expand.Validate() into the errs slice (same as for ID/Name/OrderBy) and then
return models.NewNillableGenericValidationError(errors.Join(errs...)); ensure
you still validate Namespace (e.g., non-empty) and call i.Expand.Validate(), but
push their resulting errors into errs rather than returning immediately.
🤖 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 `@api/spec/packages/aip/src/billing/operations.tsp`:
- Around line 54-58: The example query in the `@query-decorated` filter
declaration is incorrect for the deep-object operator-style filter; update the
example to use operator form compatible with ListBillingProfilesParamsFilter
(e.g., use filter[name][eq]=my-profile or filter[name][contains]=my to match the
deepObject/explode=true shape) so clients send valid operator-style filter
parameters for the filter property.

In `@openmeter/billing/profile.go`:
- Around line 372-385: OrderBy.Values() currently returns only OrderByCreatedAt,
OrderByUpdatedAt, OrderByName, so OrderByID is wrongly excluded and
OrderBy.Validate() rejects "id"; update OrderBy.Values() to include OrderByID
(and any other missing OrderBy constants) so that OrderBy.Validate() sees "id"
as valid, and verify the same fix is applied to the other Values()/Validate()
pair referenced (lines around OrderByID) to ensure consistency.

In `@openmeter/billing/service/profile_test.go`:
- Around line 49-133: Add a new test case to the cases slice in profile_test.go
that exercises sorting by ID: create a test with name "SortByID" that sets input
billing.ListProfilesInput{Namespace: ns, OrderBy: "id", Order: sortx.OrderAsc
(or Desc)} and in assertAdapter assert that got.OrderBy == billing.OrderByID and
got.Order == the expected sortx order; this mirrors the existing
"SortByNameAsc"/"SortByUpdatedAt" cases and locks the new sort contract for
billing.ListProfilesInput and the mapping to billing.OrderByID.

---

Outside diff comments:
In `@openmeter/billing/profile.go`:
- Around line 409-437: ListProfilesInput.Validate currently returns early for
Namespace and Expand errors instead of collecting them; update the method
(ListProfilesInput.Validate) to append validation errors for Namespace and for
i.Expand.Validate() into the errs slice (same as for ID/Name/OrderBy) and then
return models.NewNillableGenericValidationError(errors.Join(errs...)); ensure
you still validate Namespace (e.g., non-empty) and call i.Expand.Validate(), but
push their resulting errors into errs rather than returning immediately.
🪄 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: ac63c23c-897a-444a-a18d-d5ad4b622855

📥 Commits

Reviewing files that changed from the base of the PR and between 499cdc5 and 962d629.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (7)
  • api/spec/packages/aip/src/billing/operations.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billingprofiles/list.go
  • openmeter/billing/adapter/profile.go
  • openmeter/billing/httpdriver/profile.go
  • openmeter/billing/profile.go
  • openmeter/billing/service/profile_test.go

Comment thread api/spec/packages/aip/src/billing/operations.tsp
Comment thread openmeter/billing/profile.go
Comment thread openmeter/billing/service/profile_test.go
rolosp
rolosp previously approved these changes May 18, 2026
@borosr borosr force-pushed the feat/billing-v3-api-filters branch from f28b4c6 to b796418 Compare May 19, 2026 09:08
@borosr borosr requested a review from rolosp May 19, 2026 13:31
@borosr borosr force-pushed the feat/billing-v3-api-filters branch from b796418 to 9ee3534 Compare May 20, 2026 07:41

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
openmeter/billing/profile.go (1)

410-417: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Please aggregate all validation errors in ListProfilesInput.Validate().

Nice addition overall, but Line 411 and Line 415 still return early. That breaks the repo’s Validate() aggregation rule and can hide additional invalid fields in one request.

Suggested patch
 func (i ListProfilesInput) Validate() error {
-	if i.Namespace == "" {
-		return errors.New("namespace is required")
-	}
-
-	if err := i.Expand.Validate(); err != nil {
-		return fmt.Errorf("error validating expand: %w", err)
-	}
-
 	var errs []error
+	if i.Namespace == "" {
+		errs = append(errs, errors.New("namespace is required"))
+	}
+
+	if err := i.Expand.Validate(); err != nil {
+		errs = append(errs, fmt.Errorf("error validating expand: %w", err))
+	}
+
 	if i.ID != nil {
 		if err := i.ID.Validate(); err != nil {
 			errs = append(errs, err)
 		}
 	}
@@
 	if i.OrderBy != "" {
 		if err := i.OrderBy.Validate(); err != nil {
 			errs = append(errs, err)
 		}
 	}
 
 	return models.NewNillableGenericValidationError(errors.Join(errs...))
 }

As per coding guidelines, openmeter/**/*.go: “For Validate() error methods, collect all validation issues into var errs []error and return models.NewNillableGenericValidationError(errors.Join(errs...)) instead of returning on the first invalid field”.

Also applies to: 419-437

🤖 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/profile.go` around lines 410 - 417, Change
ListProfilesInput.Validate() to collect all field validation errors instead of
returning early: create a slice var errs []error, append an error when
i.Namespace == "" and append the wrapped error from i.Expand.Validate() if it
fails (referencing i.Expand.Validate), then at the end if len(errs) > 0 return
models.NewNillableGenericValidationError(errors.Join(errs...)) else return nil;
apply the same aggregation pattern for the other checks in the function (lines
handling pagination/filters referenced in the same Validate method).
🤖 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.

Outside diff comments:
In `@openmeter/billing/profile.go`:
- Around line 410-417: Change ListProfilesInput.Validate() to collect all field
validation errors instead of returning early: create a slice var errs []error,
append an error when i.Namespace == "" and append the wrapped error from
i.Expand.Validate() if it fails (referencing i.Expand.Validate), then at the end
if len(errs) > 0 return
models.NewNillableGenericValidationError(errors.Join(errs...)) else return nil;
apply the same aggregation pattern for the other checks in the function (lines
handling pagination/filters referenced in the same Validate method).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 141c3060-607d-45e8-bf77-4a05b9c8d852

📥 Commits

Reviewing files that changed from the base of the PR and between b796418 and 9ee3534.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (7)
  • api/spec/packages/aip/src/billing/operations.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billingprofiles/list.go
  • openmeter/billing/adapter/profile.go
  • openmeter/billing/httpdriver/profile.go
  • openmeter/billing/profile.go
  • openmeter/billing/service/profile_test.go

@borosr borosr force-pushed the feat/billing-v3-api-filters branch from 9ee3534 to 448689c Compare June 8, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/ignore Ignore this change when generating release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants