Skip to content

feat: add currency resolver#4756

Merged
turip merged 2 commits into
mainfrom
feat/currency-resolver
Jul 21, 2026
Merged

feat: add currency resolver#4756
turip merged 2 commits into
mainfrom
feat/currency-resolver

Conversation

@chrisgacsal

@chrisgacsal chrisgacsal commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Overview

Add currency resolver to currencies package which can be used for resolving Currency by id or code.

Fixes #(issue)

Notes for reviewer

Summary by CodeRabbit

  • New Features
    • Added namespace-aware currency resolution by ID or code, including batch resolution.
    • Extended currency listing filters to support currency_type, plus id and code filtering with configurable matching-all vs matching-any behavior.
  • Bug Fixes
    • Fixed currency type forwarding in the currencies list API.
    • Improved custom currency listing to short-circuit non-custom types and correctly apply ID/code filtering with union logic.
  • Tests
    • Added/extended coverage for currency resolver and filtering combinations.

Greptile Summary

This PR adds currency resolution by ID or code. The main changes are:

  • Adds namespace-aware single and batch currency resolvers.
  • Adds ID, code, type, union, and intersection filters.
  • Applies matching across custom and fiat currencies.
  • Wires the resolver provider and adds focused tests.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the updated code.
  • Resolver requests use supported exact-list filters.
  • Custom and fiat paths apply consistent union behavior.

Important Files Changed

Filename Overview
openmeter/currencies/currencyresolver/resolver.go Adds namespace-aware single and batch currency resolution using ID and code filters.
openmeter/currencies/service/service.go Adds shared ID and code matching for fiat and combined currency listings.
openmeter/currencies/adapter/currencies.go Adds custom-currency type filtering and union or intersection query predicates.
openmeter/currencies/service.go Extends list input with ID, currency type, and internal filter-combination options.
api/v3/handlers/currencies/list.go Maps the API currency type filter to the updated domain field.
app/common/currency.go Adds the currency resolver constructor to the application provider set.

Reviews (2): Last reviewed commit: "fix: classify invalid currency reference..." | Re-trigger Greptile

Context used (3)

  • Context used - CLAUDE.md (source)
  • Context used - AGENTS.md (source)
  • Context used - api/spec/AGENTS.md (source)

@chrisgacsal
chrisgacsal requested a review from turip July 21, 2026 06:02
@chrisgacsal chrisgacsal self-assigned this Jul 21, 2026
@chrisgacsal
chrisgacsal requested a review from a team as a code owner July 21, 2026 06:02
@chrisgacsal chrisgacsal added the release-note/ignore Ignore this change when generating release notes label Jul 21, 2026
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Currency listing now supports currency type, ID, and union or intersection matching. A namespace-aware resolver handles single and batch currency references, with API mapping, dependency wiring, and tests updated.

Changes

Currency filtering and resolution

Layer / File(s) Summary
Currency listing filter contracts and execution
openmeter/currencies/service.go, openmeter/currencies/service/..., openmeter/currencies/adapter/...
Listing applies CurrencyType, ID, and Code filters across fiat and custom currencies, with union and intersection behavior covered by tests.
Namespace-aware currency resolver
openmeter/currencies/resolver.go, openmeter/currencies/currencyresolver/*
Adds currency references, namespace-bound resolver interfaces, single and batch lookup, validation, deduplication, and not-found handling.
API mapping and dependency wiring
api/v3/handlers/currencies/*, app/common/currency.go
Maps API currency type filters to CurrencyType and registers the resolver constructor with the currency provider set.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant namespacedResolver
  participant resolver
  participant currenciesService
  namespacedResolver->>resolver: delegate resolution with namespace
  resolver->>currenciesService: ListCurrencies with ID and Code filters
  currenciesService-->>resolver: paginated currencies
  resolver-->>namespacedResolver: resolved currency map or error
Loading

Possibly related PRs

Suggested labels: area/billing

Suggested reviewers: turip

🚥 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding a new currency resolver and related support code.
✨ 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/currency-resolver

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.

Comment thread openmeter/currencies/service/service.go

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

🧹 Nitpick comments (1)
openmeter/currencies/currencyresolver/resolver.go (1)

140-148: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider classifying the "multiple active currencies" error.

This new ambiguity guard (e.g. a custom currency sharing a code with a fiat ISO code in the same namespace) returns a bare fmt.Errorf, unlike similar conflict/ambiguity situations elsewhere in this package (e.g. adapter/currencies.go's CreateCurrency uses models.NewGenericConflictError for a comparable "already exists" case). Worth considering wrapping this in a recognizable domain error type so callers/observability tooling can distinguish "ambiguous namespace data" from a generic internal error — though it's not clear "conflict" is the exact right classification here since this is discovered incidentally at read time rather than caused by the current request.

🤖 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/currencies/currencyresolver/resolver.go` around lines 140 - 148,
Classify the duplicate active-currency condition in the resolver’s byCode
validation instead of returning a bare fmt.Errorf. Introduce or reuse a
recognizable domain error type for ambiguous namespace data, preserving the
existing error message and early-return behavior so callers can distinguish this
condition from generic internal failures.
🤖 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/currencies/resolver.go`:
- Around line 20-30: Update CurrencyRef.Validate to wrap the missing ID/code
error with models.NewNillableGenericValidationError, preserving the existing
message. Adjust the exact error assertion in resolver_test.go to expect the
helper’s “validation error:” prefix while retaining
models.IsGenericValidationError compatibility.

---

Nitpick comments:
In `@openmeter/currencies/currencyresolver/resolver.go`:
- Around line 140-148: Classify the duplicate active-currency condition in the
resolver’s byCode validation instead of returning a bare fmt.Errorf. Introduce
or reuse a recognizable domain error type for ambiguous namespace data,
preserving the existing error message and early-return behavior so callers can
distinguish this condition from generic internal failures.
🪄 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: c8e41ae3-30b5-43ee-af57-bb1262ac20bb

📥 Commits

Reviewing files that changed from the base of the PR and between aee4c22 and 3237036.

📒 Files selected for processing (11)
  • api/v3/handlers/currencies/list.go
  • api/v3/handlers/currencies/list_test.go
  • app/common/currency.go
  • openmeter/currencies/adapter/currencies.go
  • openmeter/currencies/adapter/currencies_test.go
  • openmeter/currencies/currencyresolver/resolver.go
  • openmeter/currencies/currencyresolver/resolver_test.go
  • openmeter/currencies/resolver.go
  • openmeter/currencies/service.go
  • openmeter/currencies/service/service.go
  • openmeter/currencies/service/service_test.go

Comment thread openmeter/currencies/resolver.go
@chrisgacsal

Copy link
Copy Markdown
Collaborator Author

@coderabbitai Regarding the nitpick about classifying the duplicate active-currency-code condition: I am leaving this as an internal error intentionally. This state violates persisted-domain invariants: active custom codes are unique per namespace, and custom-currency validation rejects fiat codes. It is not a conflict caused by the request, so GenericConflictError would expose corrupted or legacy server data as a client-correctable 409. If machine-readable classification becomes necessary, an internal data-integrity sentinel would be more accurate than a generic conflict.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@chrisgacsal That makes sense—thanks for the clear distinction. This is a server-side data-integrity failure, not a client-caused conflict, so retaining an internal error is the right classification. An explicit integrity sentinel would indeed be the appropriate future refinement if callers need machine-readable handling.

🔎🐇


✏️ Learnings added
Learnt from: chrisgacsal
URL: https://github.com/openmeterio/openmeter/pull/4756

Timestamp: 2026-07-21T08:00:53.237Z
Learning: In `openmeter/currencies/currencyresolver/resolver.go`, duplicate active currency codes during resolution represent a persisted-domain data-integrity violation, not a request conflict: active custom codes must be unique per namespace and custom-currency validation rejects fiat codes. Keep this condition classified as an internal error; if machine-readable handling is later needed, use a dedicated data-integrity sentinel rather than `GenericConflictError`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@turip
turip enabled auto-merge (squash) July 21, 2026 08:04
@turip
turip merged commit 7a45161 into main Jul 21, 2026
27 checks passed
@turip
turip deleted the feat/currency-resolver branch July 21, 2026 08:09
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