Skip to content

fix(billing): preserve tax codes for v3 customer charges - #5328

Open
turip wants to merge 1 commit into
mainfrom
feat/fix-v3-charge-tax-config
Open

turip wants to merge 1 commit into
mainfrom
feat/fix-v3-charge-tax-config

Conversation

@turip

@turip turip commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Overview

V3 customer charge creation ignored tax_code.id and discarded stripe.code, allowing successful requests to persist a default tax code instead of the requested one. Preserve the full tax configuration through the API facade, apply the documented reference precedence, and resolve tax-code identity before constructing the persisted charge intent.

Notes for reviewer

  • HTTP-to-database regression coverage exercises both flat-fee and usage-based charges, including deprecated IDs, conflicting inputs, defaults, unknown references, and tax behavior preservation.
  • Updated the charges domain documentation to state the input precedence and resolution behavior.
  • Validation on latest main: all 18 regression cases, the tax-code persistence suite, focused affected-consumer tests, and scoped make lint-go-fast passed.
  • The earlier full make test-nocache run was interrupted after the local database became unavailable; full-suite validation remains for CI.

Summary by CodeRabbit

  • Bug Fixes
    • Customer charges now resolve tax settings consistently, including explicit tax-code references, legacy identifiers, Stripe codes, and organization defaults.
    • Unknown tax references are rejected, and selected tax identities are preserved for flat-fee and usage-based charges.
    • Invalid tax configurations receive clearer validation errors.
  • Documentation
    • Clarified tax-code precedence when creating customer charges.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge, with the previously reported non-blocking cleanup issue still present.

Fix All in Claude CodeFindings

  1. P2 Failed requests leave tax codes ▶
Fix with agent prompt
### Issue 1
openmeter/billing/charges/service/api.go:43-45
`ResolveTaxConfig` can create a tax code before the charge transaction starts. A Stripe-only request with an unmapped code can therefore leave a new tax code behind if charge creation later fails-for example, when a flat-fee request references an unknown feature. The caller receives an error, but the unused tax code stays saved.

Keep tax-code creation and charge persistence in the same transaction so failed requests roll both back.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Customer charge creation now keeps and resolves the full tax configuration before building flat-fee and usage-based charge intents.

  • Customer charges keep the tax code selected in their request.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Customer charge request] --> B[Convert full tax configuration]
  B --> C[Validate input and check namespace]
  C --> D[Resolve explicit ID or Stripe code]
  D --> E[Build charge intent]
  E --> F[Apply defaults when no code was selected]
  F --> G[Save charge in transaction]
Loading

Reviews (2) · Last reviewed commit: "fix(billing): preserve tax codes for v3 ..." · Reviewed by Greptile

@turip
turip requested a review from a team as a code owner October 21, 2026 13:44
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository: openmeterio/openmeter/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4af919e0-7a28-44d5-99e1-0a1b5d4575cf
📥 Commits

Reviewing files that changed from the base of the PR and between 6f024e7 and 1849fcf.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: openmeterio/openmeter/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e4edc6fb-a83d-4c58-947f-de41df65540b
📥 Commits

Reviewing files that changed from the base of the PR and between 4309400 and 6f024e7.

📒 Files selected for processing: 6
  • api/v3/handlers/billingprofiles/convert.go
  • api/v3/handlers/customers/charges/convert.go
  • openmeter/billing/charges/README.md
  • openmeter/billing/charges/api.go
  • openmeter/billing/charges/service/api.go
  • openmeter/billing/charges/service/taxcode_test.go

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

📝 Walkthrough

Customer charge creation now accepts full tax configurations, resolves tax-code references through the product catalog service, and stores the resolved configuration. Added tests cover reference precedence, defaults, unknown references, and persistence.

Changes: Customer charge tax configuration

Layer / File(s) Summary
Parse and validate tax configuration
api/v3/handlers/billingprofiles/convert.go, api/v3/handlers/customers/charges/convert.go, openmeter/billing/charges/api.go
The exported full tax-config parser is used for flat-fee and usage-based requests. CreateCustomerChargeInput now uses and validates productcatalog.TaxConfig.
Resolve tax configuration during charge creation
openmeter/billing/charges/service/api.go
CreateCustomerCharge checks namespace lockdown, resolves a cloned tax configuration through the product catalog service, and stores the resolved tax-code configuration in the charge intent.
Document and test reference precedence
openmeter/billing/charges/README.md, openmeter/billing/charges/service/taxcode_test.go
The README documents reference precedence. HTTP/API tests check precedence, defaults, unknown references, and persisted tax identity for both charge types.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant CustomerChargeAPI
  participant CreateCustomerCharge
  participant TaxCodeService
  participant ChargeIntent
  CustomerChargeAPI->>CreateCustomerCharge: Send parsed tax configuration
  CreateCustomerCharge->>TaxCodeService: Resolve tax configuration
  TaxCodeService-->>CreateCustomerCharge: Return resolved tax configuration
  CreateCustomerCharge->>ChargeIntent: Store resolved tax-code configuration
Loading

Suggested reviewers: galexihu, borosr, mark-vass-konghq

Merge Risk: ⚪ Minimal · up to 6f024

The reviewed charge paths retain the selected tax code and tax behavior. No identified issue blocks merging; CI should complete the full test run.

Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preserving tax codes for v3 customer charges.
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: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@turip turip added release-note/bug-fix Release note: Bug Fixes area/billing labels Oct 21, 2026
Comment on lines +43 to +45
taxConfig := input.TaxConfig.Clone()
if err := productcatalog.ResolveTaxConfig(ctx, s.taxCodeService, input.Namespace, &taxConfig); err != nil {
return charges.CustomerCharge{}, fmt.Errorf("resolving charge tax config: %w", err)

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.

P2 Failed requests leave tax codes

ResolveTaxConfig can create a tax code before the charge transaction starts. A Stripe-only request with an unmapped code can therefore leave a new tax code behind if charge creation later fails—for example, when a flat-fee request references an unknown feature. The caller receives an error, but the unused tax code stays saved.

Keep tax-code creation and charge persistence in the same transaction so failed requests roll both back.

Prompt To Fix With AI
This is a comment left during a code review.
Path: openmeter/billing/charges/service/api.go
Line: 43-45

Comment:
**Failed requests leave tax codes**

`ResolveTaxConfig` can create a tax code before the charge transaction starts. A Stripe-only request with an unmapped code can therefore leave a new tax code behind if charge creation later fails—for example, when a flat-fee request references an unknown feature. The caller receives an error, but the unused tax code stays saved.

Keep tax-code creation and charge persistence in the same transaction so failed requests roll both back.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We accept leftover tax codes from failed charge creation for now and are leaving this out of scope for this PR. We plan to implement a proper resolver later, which will ensure these tax codes are not left behind when charge creation fails.

@turip
turip force-pushed the feat/fix-v3-charge-tax-config branch from 6f024e7 to 1849fcf Compare October 21, 2026 13:51

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant