chore: charges add custom currency support#4755
Conversation
📝 WalkthroughWalkthroughThis PR introduces ChangesCustom currency support
Estimated code review effort: 5 (Critical) | ~150 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant CreateCustomerChargesHandler
participant ChargesService
participant CurrencyResolver
Client->>CreateCustomerChargesHandler: submit flat-fee or usage-based charge
CreateCustomerChargesHandler->>ChargesService: CreateCustomerCharge(input)
ChargesService->>CurrencyResolver: resolve currency code
CurrencyResolver-->>ChargesService: return currencies.Currency
ChargesService-->>CreateCustomerChargesHandler: return Charge
CreateCustomerChargesHandler-->>Client: return API charge
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
523a84d to
7854f8e
Compare
|
Too many files changed for review. ( Bypass the limit by tagging |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
api/v3/handlers/customers/charges/convert_test.go (1)
1-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider adding tests for the new
CreateCustomerChargeInputbuilders.This file only swaps the currency test fixture; I don't see tests exercising
fromAPICreateChargeFlatFeeRequest/fromAPICreateChargeUsageBasedRequestin convert.go, which changed their return type entirely (fromChargeIntenttoCreateCustomerChargeInputwith nestedFlatFee/UsageBasedpayloads). Worth confirming coverage exists somewhere, or adding cases here.As per path instructions for
**/*_test.go: "Make sure the tests are comprehensive and cover the changes."🤖 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 `@api/v3/handlers/customers/charges/convert_test.go` around lines 1 - 16, Add focused tests in this charges conversion test file for fromAPICreateChargeFlatFeeRequest and fromAPICreateChargeUsageBasedRequest, asserting each returns the correct CreateCustomerChargeInput variant and preserves its nested FlatFee or UsageBased payload fields, including the selected currency fixture. Cover representative valid inputs and the changed return structure.Source: Path instructions
openmeter/billing/charges/creditpurchase/service/create.go (1)
24-26: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider using
.IsCustom()for better encapsulation.Since the new
currencies.Currencyabstraction provides anIsCustom()method, consider using it here for cleaner encapsulation instead of comparing the underlying type againstcurrencyx.CurrencyTypeCustom.♻️ Proposed refactor
- if input.Intent.Currency.Type() == currencyx.CurrencyTypeCustom { + if input.Intent.Currency.IsCustom() { return creditpurchase.ChargeWithGatheringLine{}, fmt.Errorf("custom currency %s is not supported for credit purchases: %w", input.Intent.Currency.GetCode(), meta.ErrCustomCurrencyNotSupported) }🤖 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/creditpurchase/service/create.go` around lines 24 - 26, Update the currency validation in the credit purchase creation flow to use input.Intent.Currency.IsCustom() instead of comparing Currency.Type() with currencyx.CurrencyTypeCustom. Keep the existing error message and return behavior unchanged.openmeter/billing/charges/creditpurchase/adapter/funded_credit_activity_test.go (1)
281-282: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrefer
s.T().Context()overcontext.Background().As per the coding guidelines, you should use the test context instead of
context.Background()to ensure proper context propagation and timely test cancellation.♻️ Proposed fix
func (s *ListFundedCreditActivitiesSuite) TestFiltersByCurrency() { - ctx := context.Background() + ctx := s.T().Context() ns := "test-funded-activity-currency"🤖 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/creditpurchase/adapter/funded_credit_activity_test.go` around lines 281 - 282, Update TestFiltersByCurrency in ListFundedCreditActivitiesSuite to initialize ctx from s.T().Context() instead of context.Background(), preserving the existing test behavior while propagating test cancellation.Source: Coding guidelines
openmeter/billing/charges/service/pendinglines.go (1)
115-121: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePrefer using
currencies.NewFiatCurrencyfor instantiation.Instead of manually building the fiat currency and initializing the
currencies.Currencystruct, you can use theNewFiatCurrencyconstructor. This provides better encapsulation and stays consistent with its usage ininvoice.go.♻️ Proposed refactor
- currency, err := currencyx.NewCurrencyBuilder(currencyx.CurrencyTypeFiat). - WithCode(input.Currency). - Build() + resolvedCurrency, err := currencies.NewFiatCurrency(input.Currency) if err != nil { return nil, fmt.Errorf("resolving fiat currency %q: %w", input.Currency, err) } - resolvedCurrency := currencies.Currency{Currency: currency}🤖 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/service/pendinglines.go` around lines 115 - 121, Replace the manual fiat currency builder and direct currencies.Currency initialization in the pending-line flow with currencies.NewFiatCurrency, preserving input.Currency and the existing error propagation behavior; follow the constructor usage established in invoice.go.tools/migrate/migrations/20260720093016_charges-custom-currencies.down.sql (1)
4-8: 🩺 Stability & Availability | 🔵 TrivialRollback heads-up:
SET NOT NULLwill fail once custom-currency charges exist.Just so it's on your radar: reverting
currencyback toNOT NULLerrors out if any charge row was created withcustom_currency_idset (i.e.currencyNULL), and droppingcustom_currency_iddiscards that data. That's inherent to reverting the feature, not a hand-edit ask — but worth knowing before relying on this down-migration in an environment where custom currencies have already been used.🤖 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 `@tools/migrate/migrations/20260720093016_charges-custom-currencies.down.sql` around lines 4 - 8, Update the down migration for charge_usage_based, charge_flat_fees, and charge_credit_purchases to handle rows with custom_currency_id before dropping that column and restoring currency to NOT NULL. Preserve or explicitly remove those custom-currency rows according to the project’s rollback policy, ensuring the migration does not fail on existing NULL currency values.
🤖 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/charges/charge.go`:
- Around line 190-212: Update Charge.GetCurrency to match the ChargeAccessor
interface by returning only currencies.Currency. Remove error returns and handle
nil or invalid charge cases using the established zero-value currency behavior,
while preserving the existing currency lookup for valid flat-fee,
credit-purchase, and usage-based charges.
In `@openmeter/currencies/currency.go`:
- Around line 60-66: Update Currency.Validate in
openmeter/currencies/currency.go (lines 60-66) to collect validation failures,
preserve field context through wrapped errors, and return
models.NewNillableGenericValidationError(errors.Join(errs...)); update the
Validate method in openmeter/currencies/adapter/currencies.go (lines 30-40) to
collect both validation conditions and return them through the same helper.
---
Nitpick comments:
In `@api/v3/handlers/customers/charges/convert_test.go`:
- Around line 1-16: Add focused tests in this charges conversion test file for
fromAPICreateChargeFlatFeeRequest and fromAPICreateChargeUsageBasedRequest,
asserting each returns the correct CreateCustomerChargeInput variant and
preserves its nested FlatFee or UsageBased payload fields, including the
selected currency fixture. Cover representative valid inputs and the changed
return structure.
In
`@openmeter/billing/charges/creditpurchase/adapter/funded_credit_activity_test.go`:
- Around line 281-282: Update TestFiltersByCurrency in
ListFundedCreditActivitiesSuite to initialize ctx from s.T().Context() instead
of context.Background(), preserving the existing test behavior while propagating
test cancellation.
In `@openmeter/billing/charges/creditpurchase/service/create.go`:
- Around line 24-26: Update the currency validation in the credit purchase
creation flow to use input.Intent.Currency.IsCustom() instead of comparing
Currency.Type() with currencyx.CurrencyTypeCustom. Keep the existing error
message and return behavior unchanged.
In `@openmeter/billing/charges/service/pendinglines.go`:
- Around line 115-121: Replace the manual fiat currency builder and direct
currencies.Currency initialization in the pending-line flow with
currencies.NewFiatCurrency, preserving input.Currency and the existing error
propagation behavior; follow the constructor usage established in invoice.go.
In `@tools/migrate/migrations/20260720093016_charges-custom-currencies.down.sql`:
- Around line 4-8: Update the down migration for charge_usage_based,
charge_flat_fees, and charge_credit_purchases to handle rows with
custom_currency_id before dropping that column and restoring currency to NOT
NULL. Preserve or explicitly remove those custom-currency rows according to the
project’s rollback policy, ensuring the migration does not fail on existing NULL
currency values.
🪄 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: 0c9e2ffc-fdf8-4853-a0dd-2f9b15f0f6f0
⛔ Files ignored due to path filters (33)
openmeter/ent/db/chargecreditpurchase.gois excluded by!**/ent/db/**openmeter/ent/db/chargecreditpurchase/chargecreditpurchase.gois excluded by!**/ent/db/**openmeter/ent/db/chargecreditpurchase/where.gois excluded by!**/ent/db/**openmeter/ent/db/chargecreditpurchase_create.gois excluded by!**/ent/db/**openmeter/ent/db/chargecreditpurchase_query.gois excluded by!**/ent/db/**openmeter/ent/db/chargecreditpurchase_update.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee/chargeflatfee.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee/where.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee_create.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee_query.gois excluded by!**/ent/db/**openmeter/ent/db/chargeflatfee_update.gois excluded by!**/ent/db/**openmeter/ent/db/chargessearchv1.gois excluded by!**/ent/db/**openmeter/ent/db/chargessearchv1/chargessearchv1.gois excluded by!**/ent/db/**openmeter/ent/db/chargessearchv1/where.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased/chargeusagebased.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased/where.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased_create.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased_query.gois excluded by!**/ent/db/**openmeter/ent/db/chargeusagebased_update.gois excluded by!**/ent/db/**openmeter/ent/db/client.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency/customcurrency.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency/where.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency_create.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency_query.gois excluded by!**/ent/db/**openmeter/ent/db/customcurrency_update.gois excluded by!**/ent/db/**openmeter/ent/db/entmixinaccessor.gois excluded by!**/ent/db/**openmeter/ent/db/migrate/schema.gois excluded by!**/ent/db/**openmeter/ent/db/mutation.gois excluded by!**/ent/db/**openmeter/ent/db/runtime.gois excluded by!**/ent/db/**tools/migrate/migrations/atlas.sumis excluded by!**/*.sum,!**/*.sum
📒 Files selected for processing (126)
api/v3/handlers/customers/charges/convert.goapi/v3/handlers/customers/charges/convert_test.goapi/v3/handlers/customers/charges/create.goapi/v3/handlers/customers/charges/handler.goapi/v3/handlers/customers/credits/convert.goapi/v3/handlers/customers/credits/convert_test.goapi/v3/server/server.goapp/common/billing.goapp/common/charges.goapp/common/openmeter_billingworker.gocmd/billing-worker/wire_gen.gocmd/jobs/internal/wire.gocmd/jobs/internal/wire_gen.gocmd/server/wire_gen.goopenmeter/billing/charges/adapter/search_test.goopenmeter/billing/charges/api.goopenmeter/billing/charges/charge.goopenmeter/billing/charges/creditpurchase/adapter.goopenmeter/billing/charges/creditpurchase/adapter/charge.goopenmeter/billing/charges/creditpurchase/adapter/funded_credit_activity.goopenmeter/billing/charges/creditpurchase/adapter/funded_credit_activity_test.goopenmeter/billing/charges/creditpurchase/adapter/mapper.goopenmeter/billing/charges/creditpurchase/charge.goopenmeter/billing/charges/creditpurchase/charge_test.goopenmeter/billing/charges/creditpurchase/service/create.goopenmeter/billing/charges/creditpurchase/service/external_test.goopenmeter/billing/charges/creditpurchase/service/get.goopenmeter/billing/charges/creditpurchase/service/promotional_test.goopenmeter/billing/charges/creditpurchase/service/void.goopenmeter/billing/charges/flatfee/adapter/charge.goopenmeter/billing/charges/flatfee/adapter/detailedline_test.goopenmeter/billing/charges/flatfee/adapter/intentoverride.goopenmeter/billing/charges/flatfee/adapter/intentoverride_test.goopenmeter/billing/charges/flatfee/adapter/mapper.goopenmeter/billing/charges/flatfee/adapter/realizationrun_test.goopenmeter/billing/charges/flatfee/charge.goopenmeter/billing/charges/flatfee/charge_test.goopenmeter/billing/charges/flatfee/service/create.goopenmeter/billing/charges/flatfee/service/creditsonly.goopenmeter/billing/charges/flatfee/service/lineengine.goopenmeter/billing/charges/flatfee/service/manualedit.goopenmeter/billing/charges/flatfee/service/realizations/credittheninvoice.goopenmeter/billing/charges/flatfee/service/realizations/preview.goopenmeter/billing/charges/lineage/lineage_test.goopenmeter/billing/charges/lineage/service.goopenmeter/billing/charges/lineage/service/service.goopenmeter/billing/charges/meta/charge.goopenmeter/billing/charges/meta/errors.goopenmeter/billing/charges/meta/intent.goopenmeter/billing/charges/models/chargemeta/model.goopenmeter/billing/charges/service.goopenmeter/billing/charges/service/advance.goopenmeter/billing/charges/service/api.goopenmeter/billing/charges/service/base_test.goopenmeter/billing/charges/service/create.goopenmeter/billing/charges/service/creditpurchase_test.goopenmeter/billing/charges/service/invoicable_test.goopenmeter/billing/charges/service/invoice.goopenmeter/billing/charges/service/lineage_test.goopenmeter/billing/charges/service/pendinglines.goopenmeter/billing/charges/service/recognition.goopenmeter/billing/charges/service/service.goopenmeter/billing/charges/service/taxcode_test.goopenmeter/billing/charges/service/truncation_test.goopenmeter/billing/charges/testutils/service.goopenmeter/billing/charges/usagebased/adapter/charge.goopenmeter/billing/charges/usagebased/adapter/detailedline_test.goopenmeter/billing/charges/usagebased/adapter/intentoverride.goopenmeter/billing/charges/usagebased/adapter/intentoverride_test.goopenmeter/billing/charges/usagebased/adapter/mapper.goopenmeter/billing/charges/usagebased/charge.goopenmeter/billing/charges/usagebased/detailedline.goopenmeter/billing/charges/usagebased/rating.goopenmeter/billing/charges/usagebased/service/create.goopenmeter/billing/charges/usagebased/service/creditheninvoice_test.goopenmeter/billing/charges/usagebased/service/creditsonly_test.goopenmeter/billing/charges/usagebased/service/lineengine.goopenmeter/billing/charges/usagebased/service/linemapper.goopenmeter/billing/charges/usagebased/service/rating/service_test.goopenmeter/billing/charges/usagebased/service/rating/subtract/subtract_test.goopenmeter/billing/charges/usagebased/service/rating/testutils/testutils.goopenmeter/billing/charges/usagebased/service/run/payment_test.goopenmeter/billing/charges/usagebased/service/triggers.goopenmeter/billing/charges/usagebased/service/triggers_test.goopenmeter/billing/creditgrant/service/service.goopenmeter/billing/rating/line.goopenmeter/billing/rating/service/detailedline.goopenmeter/billing/stdinvoiceline.goopenmeter/billing/worker/subscriptionsync/service/base_test.goopenmeter/billing/worker/subscriptionsync/service/creditsonly_test.goopenmeter/billing/worker/subscriptionsync/service/reconciler/patchcharge_test.goopenmeter/billing/worker/subscriptionsync/service/reconciler/patchchargeflatfee.goopenmeter/billing/worker/subscriptionsync/service/reconciler/patchchargeusagebased.goopenmeter/billing/worker/subscriptionsync/service/sync_credittheninvoice_test.goopenmeter/billing/worker/subscriptionsync/service/targetstate/targetstate.goopenmeter/billing/worker/subscriptionsync/service/targetstate/targetstateitem.goopenmeter/currencies/adapter/currencies.goopenmeter/currencies/currency.goopenmeter/currencies/currency_test.goopenmeter/currencies/testutils/currency/currency.goopenmeter/ent/schema/charges.goopenmeter/ent/schema/chargescreditpurchase.goopenmeter/ent/schema/chargesflatfee.goopenmeter/ent/schema/chargesusagebased.goopenmeter/ent/schema/custom_currencies.goopenmeter/ledger/chargeadapter/creditpurchase.goopenmeter/ledger/chargeadapter/creditpurchase_test.goopenmeter/ledger/chargeadapter/flatfee.goopenmeter/ledger/chargeadapter/flatfee_test.goopenmeter/ledger/chargeadapter/usagebased.goopenmeter/ledger/chargeadapter/usagebased_test.goopenmeter/ledger/customerbalance/expired_loader_test.goopenmeter/ledger/customerbalance/service.goopenmeter/ledger/customerbalance/service_test.goopenmeter/ledger/customerbalance/testenv_test.goopenmeter/ledger/recognizer/recognize.goopenmeter/ledger/recognizer/service.goopenmeter/ledger/recognizer/service_test.goopenmeter/server/router/router.goopenmeter/server/server_test.gopkg/framework/entutils/entedge/ornil.gotest/app/stripe/invoice_credits_test.gotest/credits/base.gotools/migrate/migrations/20260720093016_charges-custom-currencies.down.sqltools/migrate/migrations/20260720093016_charges-custom-currencies.up.sqltools/migrate/views.sql
💤 Files with no reviewable changes (1)
- openmeter/billing/charges/creditpurchase/service/get.go
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
openmeter/billing/charges/models/chargemeta/model.go (1)
37-43: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winPreserve field context in validation errors.
As per coding guidelines, please wrap the errors for
IntentandIntentMutableFieldsto preserve their field context so it's clear where the validation failed.♻️ Proposed fix
- if err := i.Intent.Validate(); err != nil { - errs = append(errs, err) - } - - if err := i.IntentMutableFields.Validate(); err != nil { - errs = append(errs, err) - } + if err := i.Intent.Validate(); err != nil { + errs = append(errs, fmt.Errorf("intent: %w", err)) + } + + if err := i.IntentMutableFields.Validate(); err != nil { + errs = append(errs, fmt.Errorf("intent mutable fields: %w", err)) + }🤖 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/models/chargemeta/model.go` around lines 37 - 43, Update the validation error handling in the model’s validation method for Intent and IntentMutableFields to wrap each returned error with its corresponding field name before appending it to errs. Preserve the underlying validation error while making the failing field explicit.Source: Coding guidelines
🧹 Nitpick comments (1)
openmeter/billing/charges/usagebased/adapter/detailedline.go (1)
218-221: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the required
FromDB...conversion naming.This helper converts a database entity into a domain model, but
fromDBDetailedLinedoes not follow the repository’sFromDB...naming convention. Rename it consistently and update the call site.🤖 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/adapter/detailedline.go` around lines 218 - 221, Rename the database-to-domain conversion helper fromDBDetailedLine to the repository-standard FromDBDetailedLine name, and update every call site to use the renamed function.Source: Coding guidelines
🤖 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/charges/models/chargemeta/model.go`:
- Around line 37-43: Update the validation error handling in the model’s
validation method for Intent and IntentMutableFields to wrap each returned error
with its corresponding field name before appending it to errs. Preserve the
underlying validation error while making the failing field explicit.
---
Nitpick comments:
In `@openmeter/billing/charges/usagebased/adapter/detailedline.go`:
- Around line 218-221: Rename the database-to-domain conversion helper
fromDBDetailedLine to the repository-standard FromDBDetailedLine name, and
update every call site to use the renamed function.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 622ad0eb-af8a-4dd5-8f16-e74a8bd0540b
📒 Files selected for processing (17)
openmeter/billing/charges/creditpurchase/adapter/charge.goopenmeter/billing/charges/creditpurchase/adapter/funded_credit_activity.goopenmeter/billing/charges/creditpurchase/adapter/mapper.goopenmeter/billing/charges/creditpurchase/adapter/predicate.goopenmeter/billing/charges/flatfee/adapter/charge.goopenmeter/billing/charges/flatfee/adapter/intentoverride.goopenmeter/billing/charges/flatfee/adapter/mapper.goopenmeter/billing/charges/flatfee/adapter/realizationrun.goopenmeter/billing/charges/meta/intent.goopenmeter/billing/charges/models/chargemeta/model.goopenmeter/billing/charges/usagebased/adapter/charge.goopenmeter/billing/charges/usagebased/adapter/detailedline.goopenmeter/billing/charges/usagebased/adapter/intentoverride.goopenmeter/billing/charges/usagebased/adapter/mapper.goopenmeter/billing/charges/usagebased/adapter/realizationrun.goopenmeter/currencies/adapter/currencies.goopenmeter/currencies/currency.go
🚧 Files skipped from review as they are similar to previous changes (7)
- openmeter/billing/charges/meta/intent.go
- openmeter/billing/charges/creditpurchase/adapter/funded_credit_activity.go
- openmeter/currencies/currency.go
- openmeter/billing/charges/flatfee/adapter/intentoverride.go
- openmeter/billing/charges/usagebased/adapter/charge.go
- openmeter/billing/charges/flatfee/adapter/charge.go
- openmeter/billing/charges/creditpurchase/adapter/charge.go
Overview
This patch uses the shared custom currency/fiat union types in charges. Right now all create calls return errors if custom currency is being used.
On the ledger side the same guard is in place, for easier identification of the unsupported operands.
Notes for reviewer
Greptile Summary
This PR adds custom-currency support to billing charges. The main changes are:
Confidence Score: 4/5
Credit-purchase creation, currency-filtered activity queries, and database upgrades can fail on the updated paths.
Credit-purchase adapters and lineage handling, shared charge mapping, and both custom-currency migration files.
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Credit purchase request] --> B[Resolve currency by namespace and code] B --> C[Normalize amount precision] C --> D[Persist charge] D --> E{Currency type} E -->|Fiat| F[Store currency code] E -->|Custom| G[Store custom currency ID] F --> H[Map charge with resolved currency] G --> H H --> I[Funded activity and lineage flows]%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% flowchart TD A[Credit purchase request] --> B[Resolve currency by namespace and code] B --> C[Normalize amount precision] C --> D[Persist charge] D --> E{Currency type} E -->|Fiat| F[Store currency code] E -->|Custom| G[Store custom currency ID] F --> H[Map charge with resolved currency] G --> H H --> I[Funded activity and lineage flows]Comments Outside Diff (1)
openmeter/billing/charges/creditpurchase/adapter/charge.go, line 84-89 (link)service.Createresolves the requested currency, but only uses it for amount normalization before calling this adapter. This newchargemeta.CreateInputrequiresCurrency, yet the value is not carried throughcreditpurchase.CreateInputor set here, so every valid credit-purchase create returnscurrency is requiredbefore persistence.Context Used: AGENTS.md (source)
Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "chore: charges add custom currency suppo..." | Re-trigger Greptile
Context used:
Summary by CodeRabbit