Skip to content

feat: add invoice v3 list endpoint#4613

Merged
tothandras merged 2 commits into
mainfrom
feat/v3-invoice-api-list
Jun 30, 2026
Merged

feat: add invoice v3 list endpoint#4613
tothandras merged 2 commits into
mainfrom
feat/v3-invoice-api-list

Conversation

@borosr

@borosr borosr commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Overview

Notes for reviewer

Summary by CodeRabbit

  • New Features

    • Added support for listing invoices across the API and SDKs.
    • Invoice lists now support pagination, sorting, and filtering by customer, status, and date fields.
    • Added a clearer short invoice status type for API responses.
  • Bug Fixes

    • Invoice listing now excludes gathering invoices where expected.
    • Customer-related invoice lookups now use more precise filtering.

@borosr
borosr requested a review from a team as a code owner June 30, 2026 12:33
@borosr
borosr requested review from rolosp, tothandras and turip June 30, 2026 12:33
@borosr borosr self-assigned this Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 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
📝 Walkthrough

Walkthrough

Adds a GET /openmeter/billing/invoices endpoint across the v3 Go server, TypeSpec spec, and JavaScript SDK. Billing invoice query inputs are refactored from string/time-range fields (Customers []string, IssuedAfter/Before, etc.) to typed filter objects (CustomerID *filter.FilterULID, IssuedAt/PeriodStart/CreatedAt *filter.FilterTime). All existing call sites and tests are updated to match.

Changes

Billing invoices list flow

Layer / File(s) Summary
Typed invoice filters and short status
pkg/filter/filter.go, openmeter/billing/invoice.go, openmeter/billing/stdinvoice.go
ListInvoicesInput and ListInvoicesAdapterInput replace string/time-range fields with typed CustomerID *filter.FilterULID and *filter.FilterTime filter pointers. InvoiceShortStatus type is added with Values() and Validate(). NewFilterTime converts optional after/before bounds into a FilterTime predicate.
Service and adapter filter mapping
openmeter/billing/service/invoice.go, openmeter/billing/adapter/invoice.go, openmeter/billing/httpdriver/invoice.go, openmeter/billing/validators/customer/customer.go
Service.ListInvoices maps consolidated filter fields into adapter input. The adapter replaces explicit where-clauses with filter.ApplyToQuery calls. The HTTP driver constructs typed filter objects from legacy inputs. Delete-customer validation queries by CustomerID.
API contract and generated server wiring
api/spec/packages/aip/src/invoices/operations.tsp, api/v3/api.gen.go
TypeSpec gains ListInvoicesParamsFilter with deep-object query param, annotated with UnstableExtension. Generated Go code adds InvoicePagePaginatedResponse, ListInvoicesParams, server interface method, middleware wrapper, route, and updated embedded Swagger spec.
v3 handler sort mapping and list endpoint
api/v3/handlers/billinginvoices/convert.go, api/v3/handlers/billinginvoices/handler.go, api/v3/handlers/billinginvoices/list.go, api/v3/server/routes.go
FromAPIInvoiceSortField maps sort-field strings to legacy InvoiceOrderBy. Handler interface gains ListBillingInvoices(). The list handler parses pagination (defaults page 1/size 20), sort, and filter fields, returning a paginated JSON response. Server route wires it all together.
JavaScript SDK and spec updates
api/spec/packages/aip-client-javascript/...
Models, schemas, types, client function listInvoices, SDK Invoices.list method, barrel exports, and README are all updated to expose the new list operation.
E2E coverage for invoice listing
e2e/billinginvoices_v3_test.go, e2e/v3helpers_test.go
TestV3ListBillingInvoices covers gathering exclusion, customer/status filtering, sort acceptance, unknown-customer empty results, invalid operator 400 error, and pagination metadata. ListBillingInvoices helper builds query strings with optional params.
Invoice list call-site updates in tests
openmeter/billing/charges/service/..., openmeter/billing/worker/subscriptionsync/service/..., test/billing/..., test/subscription/...
All existing test call sites switch from Customers: []string{...} to CustomerID: &filter.FilterULID{...} equality predicates to match the updated input schema.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

area/billing

Suggested reviewers

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

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% 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 the invoice v3 list 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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/v3-invoice-api-list

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.

@borosr borosr added the release-note/feature Release note: Exciting New Features label Jun 30, 2026
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds the v3 invoice list endpoint and generated client support. The main changes are:

  • New GET /openmeter/billing/invoices API and handler wiring.
  • Pagination, filtering, and sorting for invoice lists.
  • Generated OpenAPI, Go, and JavaScript SDK surfaces.
  • Billing service and adapter updates for shared filter predicates.
  • End-to-end coverage for listing standard invoices.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
api/v3/handlers/billinginvoices/list.go Adds the v3 invoice list handler with page defaults, filters, and created_at ascending default sorting.
api/v3/handlers/billinginvoices/convert.go Adds mapping from public invoice sort fields to billing domain order fields.
openmeter/billing/adapter/invoice.go Applies shared filter predicates in the invoice adapter while preserving existing order handling.

Reviews (6): Last reviewed commit: "fix: linter" | Re-trigger Greptile

Comment thread api/v3/handlers/billinginvoices/list.go Outdated

@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: 2

🧹 Nitpick comments (1)
e2e/billinginvoices_v3_test.go (1)

442-460: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Heads up: this status-filter subtest can pass even if status filtering breaks.

It only checks that returned invoices have status draft/issued, but never asserts anything was actually returned. If the filter[status][oeq] path regressed and returned an empty page, the loop body never runs and the test still passes green. A quick require.NotEmpty(t, resp.Data, ...) (the invoice advances to a draft-family status, so it should be present) would make this actually guard the behavior.

♻️ Suggested tweak
 		require.Equal(t, http.StatusOK, status, "problem: %+v", problem)
 		require.NotNil(t, resp)
+		require.NotEmpty(t, resp.Data, "expected the customer's invoice to match the status filter")
 
 		for _, inv := range resp.Data {
🤖 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 `@e2e/billinginvoices_v3_test.go` around lines 442 - 460, The status-filter
subtest in billinginvoices_v3_test.go only validates the status of returned
items and can still pass if ListBillingInvoices returns an empty page. Update
the t.Run block around ListBillingInvoices and resp.Data to assert that at least
one invoice is returned before iterating, using the existing customerID/status
filter setup so the test actually verifies filter[status][oeq] behavior.

Source: Path instructions

🤖 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 @.agents/skills/api-filters/SKILL.md:
- Around line 345-360: The `InvoiceShortStatus.Values()` example is missing the
exclusion of `StandardInvoiceStatusGathering`, so it incorrectly treats
`gathering` as a valid filter value. Update the `Values()` example to mirror the
real `InvoiceShortStatus.Values()` behavior from `stdinvoice.go` by filtering
`validStatuses` with `lo.Without(..., StandardInvoiceStatusGathering)` before
mapping to `InvoiceShortStatus`, so `Validate()` continues to reject `gathering`
consistently.

In `@api/v3/handlers/billinginvoices/list.go`:
- Around line 53-56: The default sort in the billing invoices list handler does
not match the published contract, since `list.go` currently sets
`api.InvoiceOrderByCreatedAt` with `sortx.OrderDesc` when `sort` is omitted.
Update the defaulting logic in the `List` handler so the default order matches
the SDK/spec expectation of `created_at` ascending, and make sure any special
handling of an explicit `sort=created_at` still uses the same ordering as the
omitted case.

---

Nitpick comments:
In `@e2e/billinginvoices_v3_test.go`:
- Around line 442-460: The status-filter subtest in billinginvoices_v3_test.go
only validates the status of returned items and can still pass if
ListBillingInvoices returns an empty page. Update the t.Run block around
ListBillingInvoices and resp.Data to assert that at least one invoice is
returned before iterating, using the existing customerID/status filter setup so
the test actually verifies filter[status][oeq] behavior.
🪄 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: 071720da-ec75-43fa-8f82-9985b92dd1af

📥 Commits

Reviewing files that changed from the base of the PR and between 79c88f3 and bc7134f.

⛔ Files ignored due to path filters (1)
  • api/v3/openapi.yaml is excluded by !**/openapi.yaml
📒 Files selected for processing (30)
  • .agents/skills/api-filters/SKILL.md
  • .agents/skills/api/SKILL.md
  • api/spec/packages/aip-client-javascript/README.md
  • api/spec/packages/aip-client-javascript/src/funcs/invoices.ts
  • api/spec/packages/aip-client-javascript/src/index.ts
  • api/spec/packages/aip-client-javascript/src/models/operations/invoices.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-client-javascript/src/sdk/invoices.ts
  • api/spec/packages/aip/src/invoices/operations.tsp
  • api/v3/api.gen.go
  • api/v3/handlers/billinginvoices/convert.go
  • api/v3/handlers/billinginvoices/handler.go
  • api/v3/handlers/billinginvoices/list.go
  • api/v3/server/routes.go
  • e2e/billinginvoices_v3_test.go
  • e2e/v3helpers_test.go
  • openmeter/billing/adapter/invoice.go
  • openmeter/billing/charges/service/gathering_preview_test.go
  • openmeter/billing/httpdriver/invoice.go
  • openmeter/billing/invoice.go
  • openmeter/billing/service/invoice.go
  • openmeter/billing/stdinvoice.go
  • openmeter/billing/validators/customer/customer.go
  • openmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.go
  • openmeter/billing/worker/subscriptionsync/service/sync_test.go
  • pkg/filter/filter.go
  • test/billing/invoice_test.go
  • test/billing/lineengine_test.go
  • test/subscription/scenario_firstofmonth_test.go

Comment thread .agents/skills/api-filters/SKILL.md Outdated
Comment thread api/v3/handlers/billinginvoices/list.go Outdated
@borosr
borosr force-pushed the feat/v3-invoice-api-list branch from bc7134f to 50d9678 Compare June 30, 2026 12:48
@borosr
borosr force-pushed the feat/v3-invoice-api-list branch from 0a8cb81 to f6665e0 Compare June 30, 2026 15:05
tothandras
tothandras previously approved these changes Jun 30, 2026
@tothandras
tothandras merged commit 4e76602 into main Jun 30, 2026
29 checks passed
@tothandras
tothandras deleted the feat/v3-invoice-api-list branch June 30, 2026 16:57
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.

2 participants