Route es-tbai-exemption=S2 to Sujeta/NoExenta. Part of APP-516#41
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Routes es-tbai-exemption=S2 correctly to Sujeta.NoExenta with TipoNoExenta=S2 (rather than incorrectly emitting it under Sujeta.Exenta with an invalid CausaExencion=S2), and also routes VT/IE exemption codes to NoSujeta. The previous tag-based reverse-charge path is preserved as a fallback for non-normalized callers.
Changes:
nonExemptedTypenow consults the per-ratees-tbai-exemptionextension (S2 → TipoNoExenta=S2) in addition to the legacy invoice-wide reverse-charge tag.- Expanded
notSubjectExemptionCodesto includeVTandIE; introducedreverseChargeExemptionCodesand excluded those codes fromisExenta.newDetalleIVAnow toleratesrate.Percent == nilby emitting0.00. - Added unit tests and a round-trip JSON/XML fixture covering the new routing.
Reviewed changes
Copilot reviewed 3 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| convert/breakdown.go | Dispatcher updates: S2 → NoExenta, VT/IE → NoSujeta, nil-percent handling. |
| convert/breakdown_test.go | Tests for KeyReverseCharge, S2 via extension, and VT/IE outside-scope routing. |
| test/data/invoice-es-nl-reverse-charge.json | New input fixture for an EU reverse-charge invoice. |
| test/data/out/invoice-es-nl-reverse-charge.xml | Expected XML output verifying TipoNoExenta=S2 with zero base/cuota. |
| .gitignore | Ignore /bin/. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The converter previously mapped any rate without a percent to either NoSujeta (for OT/RL) or Exenta (everything else), so reverse-charge combos (es-tbai-exemption=S2, percent nil after addon normalization) ended up under CausaExencion=S2, which is invalid per the TBAI XSD. Extend the dispatcher to read es-tbai-exemption set by the es-tbai-v1 addon: S2 routes to Sujeta/NoExenta/TipoNoExenta=S2 with a 0% DetalleIVA, and VT/IE join OT/RL in NoSujeta. The tag-based reverse-charge fallback is preserved for invoices built without running the addon. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b6e9e33 to
1161c55
Compare
5 tasks
pmenendz
added a commit
that referenced
this pull request
May 14, 2026
The S2/reverse-charge dispatcher changes in convert/breakdown.go and the invoice-es-es-reverse-charge fixture are owned by PR #41 (fix-tbai-exemption-s2). Removing them here so this PR's diff only shows the es-tbai-regime + es-tbai-identity-type work.
3 tasks
cavalle
approved these changes
May 15, 2026
cavalle
left a comment
Contributor
There was a problem hiding this comment.
Approving to keep the flow but please review and consider the comments
Gate Convert on the addon being declared and remove the TagReverseCharge fallback in the breakdown, since the addon normalizer now guarantees es-tbai-exemption is set on every combo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80b9e31 to
912b77b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
es-tbai-exemption=S2did not work while the other values did. After addon normalization, an S2 rate has noPercent, and the converter routed any no-percent rate that wasn'tOT/RLintoSujeta.ExentawithCausaExencion=S2— invalid per the TBAI XSD, whereCausaExenciononly acceptsE1–E6.es-tbai-exemptionextension set by thees-tbai-v1addon:S2lands inSujeta.NoExentawithTipoNoExenta=S2and a zero-amountDetalleIVA;VT/IEjoinOT/RLinNoSujeta. The legacy tag-based reverse-charge path is preserved for callers that haven't run the addon.Test plan
go test ./convert/...— new tests coverKey=tax.KeyReverseCharge, manually-setes-tbai-exemption=S2, andVT/IErouting viaKey=tax.KeyOutsideScope.test/data/invoice-es-nl-reverse-charge.jsonfixture round-trips through the existing example pipeline; output XML emits<TipoNoExenta>S2</TipoNoExenta>with a0.00rate/cuota.🤖 Generated with Claude Code