Skip to content

Map reverse charge to the supplier regime's category - #46

Merged
pmenendz merged 2 commits into
mainfrom
reverse-charge-foreign-category
Jun 30, 2026
Merged

Map reverse charge to the supplier regime's category#46
pmenendz merged 2 commits into
mainfrom
reverse-charge-foreign-category

Conversation

@pmenendz

Copy link
Copy Markdown
Contributor

Problem

Converting a Stripe invoice from a Polish supplier billing an Australian customer failed with:

422: invalid-category: 'GST' not defined in regime

The invoice's regime comes from the Stripe account country (PL → Poland). Stripe reports the line tax from the customer's perspective — an Australian GST rate with taxability_reason: reverse_charge. The reverse-charge branch kept that GST category but stamped it onto the supplier's regime (PL), which only defines VAT, so GOBL rejected the combo.

Fix

A reverse charge is issued from the supplier's side: the supplier charges no tax and the customer self-accounts, so the combo must sit in the supplier's regime. Resolve the category accordingly:

  • keep the category Stripe reports when the supplier's regime already defines it (EU → EU stays VAT);
  • otherwise fall back to the regime's VAT category (EU → non-EU, e.g. PL → AU);
  • if the regime defines neither, record the Stripe tax as-is rather than emit an invalid combo.

The reverse-charge key and the regime country are unchanged. Applied to both invoices and credit notes.

For invoice.json (PL → AU) the lines now convert to VAT / PL / reverse-charge and the invoice validates (total/payable 87.50). An actual customer-country percentage (not a reverse charge) is unaffected and still maps to that country's tax via the existing foreign-tax path.

Tests

Added cases to TestFromInvoiceTaxAmountsReverseCharge and TestFromCreditNoteTaxAmountsReverseCharge covering a foreign category (AU GST) not defined in the supplier regime (PL) → VAT / PL / reverse-charge. Existing EU → EU reverse-charge behaviour (VAT / DE / reverse-charge) is unchanged. Full suite passes; go vet clean.

🤖 Generated with Claude Code

A reverse charge is issued from the supplier's side: the supplier charges
no tax and the customer self-accounts. The tax combo must therefore sit in
the supplier's regime. Previously the reverse-charge branch kept the
category Stripe reports from the customer's perspective (e.g. Australian
GST for an AU customer), which an EU supplier's regime (e.g. Poland) does
not define, so GOBL rejected the invoice with "invalid-category: 'GST' not
defined in regime".

Resolve the category against the supplier regime: keep the reported
category when the regime defines it (EU->EU stays VAT), otherwise fall back
to the regime's VAT category (EU->non-EU), keeping the reverse-charge key
and the regime country. Apply the same fix to credit notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 30, 2026 14:04

Copilot AI 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.

Pull request overview

This PR fixes reverse-charge tax combo generation when Stripe reports a customer-side tax category (e.g. AU GST) that is not defined in the supplier’s tax regime (e.g. PL), by selecting a regime-valid category (prefer reported category when defined, otherwise fall back to VAT) for reverse-charge combos on both invoices and credit notes.

Changes:

  • Adjust reverse-charge handling to map the category into the supplier regime when possible (or fall back to VAT if available).
  • Add reverseChargeCategory helper to centralize the category-selection logic.
  • Extend reverse-charge unit tests for both invoices and credit notes to cover foreign categories not defined in the supplier regime.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
lines.go Updates reverse-charge tax combo generation and introduces a helper for selecting a regime-valid reverse-charge category.
lines_test.go Adds reverse-charge test cases for supplier-regime category fallback (e.g. PL supplier with AU GST reported by Stripe).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lines.go
Comment thread lines.go
Address PR review: the fall-through (where reverseChargeCategory returns
"") deliberately does not set tax.KeyReverseCharge. It is reached only when
the supplier regime defines no reverse-charge-capable category (no VAT), and
GOBL only accepts the reverse-charge key on VAT. Forcing the key there would
make GOBL reject the line (key: must be a valid value), reintroducing the
invalid combo this PR fixes. Expand the comments to spell this out and add a
test asserting the key is not forced onto a non-VAT regime combo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pmenendz
pmenendz merged commit 9d527e9 into main Jun 30, 2026
2 checks passed
@pmenendz
pmenendz deleted the reverse-charge-foreign-category branch June 30, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants