cef: validate VATEX codes by pattern - #860
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #860 +/- ##
=======================================
Coverage 94.87% 94.87%
=======================================
Files 320 320
Lines 17431 17431
=======================================
Hits 16537 16537
Misses 553 553
Partials 341 341 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
e266bf7 to
a22ae44
Compare
The cef-vatex catalogue hard-enumerated the official CEF VATEX codes,
which left no room for the country codes that profiles admit, such as
the 24 VATEX-FR-CGI* codes of the French CTC Extended profile.
The catalogue now enforces the code shape only, via the pattern
^VATEX-[A-Z]{2}(-[A-Z0-9]+)+$, which covers all 75 official codes.
Schematrons own the allowed list for each profile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
a22ae44 to
90135ae
Compare
There was a problem hiding this comment.
Pull request overview
This PR relaxes validation of the CEF VATEX exemption reason code extension by replacing the fixed enumeration list with a regex pattern, allowing profile/country-specific VATEX codes to pass base validation while leaving stricter allow-lists to profile-specific rules.
Changes:
- Replaced the
cef-vatexcatalogue enumeration with apattern-based validation rule indata/catalogues/cef.json. - Added tests in
catalogues/cefto verify the new VATEX regex accepts official and country-specific codes and rejects malformed inputs. - Added an EN16931 addon test to confirm a country-specific VATEX code passes validation in context.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| data/catalogues/cef.json | Switches cef-vatex from enumerated values to a regex pattern for validation. |
| catalogues/cef/cef_test.go | Adds unit tests asserting the VATEX pattern matches valid codes and rejects invalid ones. |
| addons/eu/en16931/tax_combo_test.go | Adds an addon-context test ensuring a country-specific VATEX code is accepted. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "desc": { | ||
| "en": "Codes for the reasons for VAT exemption as defined by the Connecting Europe Facility (CEF)." | ||
| }, | ||
| "values": [ | ||
| { | ||
| "code": "VATEX-EU-79-C", | ||
| "name": { | ||
| "en": "Exempt based on article 79, point c of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132", | ||
| "name": { | ||
| "en": "Exempt based on article 132 of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1A", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (a) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1B", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (b) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1C", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (c) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1D", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (d) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1E", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (e) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1F", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (f) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1G", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (g) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1H", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (h) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1I", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (i) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1J", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (j) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1K", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (k) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1L", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (l) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1M", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (m) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1N", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (n) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1O", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (o) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1P", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (p) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-132-1Q", | ||
| "name": { | ||
| "en": "Exempt based on article 132, section 1 (q) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143", | ||
| "name": { | ||
| "en": "Exempt based on article 143 of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1A", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (a) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1B", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (b) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1C", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (c) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1D", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (d) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1E", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (e) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1F", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (f) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1FA", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (fa) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1G", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (g) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1H", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (h) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1I", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (i) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1J", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (j) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1K", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (k) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-143-1L", | ||
| "name": { | ||
| "en": "Exempt based on article 143, section 1 (l) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148", | ||
| "name": { | ||
| "en": "Exempt based on article 148 of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-A", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (a) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-B", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (b) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-C", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (c) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-D", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (d) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-E", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (e) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-F", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (f) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-148-G", | ||
| "name": { | ||
| "en": "Exempt based on article 148, section (g) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151", | ||
| "name": { | ||
| "en": "Exempt based on article 151 of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1A", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (a) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1AA", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (aa) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1B", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (b) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1C", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (c) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1D", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (d) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-151-1E", | ||
| "name": { | ||
| "en": "Exempt based on article 151, section 1 (e) of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-309", | ||
| "name": { | ||
| "en": "Exempt based on article 309 of Council Directive 2006/112/EC" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-AE", | ||
| "name": { | ||
| "en": "Reverse charge" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-D", | ||
| "name": { | ||
| "en": "Travel agents VAT scheme." | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-F", | ||
| "name": { | ||
| "en": "Second hand goods VAT scheme." | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-G", | ||
| "name": { | ||
| "en": "Export outside the EU" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-I", | ||
| "name": { | ||
| "en": "Works of art VAT scheme." | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-IC", | ||
| "name": { | ||
| "en": "Intra-community supply" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-J", | ||
| "name": { | ||
| "en": "Collectors items and antiques VAT scheme." | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-EU-O", | ||
| "name": { | ||
| "en": "Not subject to VAT" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-FR-FRANCHISE", | ||
| "name": { | ||
| "en": "France domestic VAT franchise in base" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-FR-CNWVAT", | ||
| "name": { | ||
| "en": "France domestic Credit Notes without VAT, due to supplier forfeit of VAT for discount" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-29", | ||
| "name": { | ||
| "en": "Financial services mentioned in Article 29 of the VAT Regulations" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-29-7", | ||
| "name": { | ||
| "en": "Life insurance services mentioned in Article 29 of the VAT Regulations" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-30", | ||
| "name": { | ||
| "en": "Real estate transactions mentioned in Article 30 of the VAT Regulations" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-32", | ||
| "name": { | ||
| "en": "Export of goods" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-33", | ||
| "name": { | ||
| "en": "Export of services" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-34-1", | ||
| "name": { | ||
| "en": "The international transport of goods" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-34-2", | ||
| "name": { | ||
| "en": "International transport of passengers" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-34-3", | ||
| "name": { | ||
| "en": "Services directly connected and incidental to a supply of international passenger transport" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-34-4", | ||
| "name": { | ||
| "en": "Supply of a qualifying means of transport" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-34-5", | ||
| "name": { | ||
| "en": "Any services relating to goods or passenger transportation, as defined in Article 25 of the VAT Regulations" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-35", | ||
| "name": { | ||
| "en": "Medicines and medical equipment" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-36", | ||
| "name": { | ||
| "en": "Qualifying metals" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-EDU", | ||
| "name": { | ||
| "en": "Private education to citizen" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-HEA", | ||
| "name": { | ||
| "en": "Private healthcare to citizen" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-MLTRY", | ||
| "name": { | ||
| "en": "Supply of qualified military goods" | ||
| } | ||
| }, | ||
| { | ||
| "code": "VATEX-SA-OOS", | ||
| "name": { | ||
| "en": "Reason is free text, to be provided by the taxpayer on a case-by-case basis" | ||
| } | ||
| } | ||
| ] | ||
| "pattern": "^VATEX-[A-Z]{2}(-[A-Z0-9]+)+$" |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
addons/eu/en16931/tax_combo_test.go:154
- This subtest name claims it verifies that a country-specific VATEX code "passes the catalogue pattern", but it only asserts that
rules.Validatereturns no error. The EN16931 tax combo rules currently don't validatecef-vatexvalues against the catalogue definition, so this test would pass even if the pattern were missing/incorrect. Add an explicit assertion that thecef-vatexextension value matches the registered definition (e.g. viatax.ExtensionHasValidCode("cef-vatex")).
norm.Normalize(c, tax.AddonContext(en16931.V2017))
err := rules.Validate(c, tax.AddonContext(en16931.V2017))
assert.NoError(t, err)
})
data/catalogues/cef.json: thecef-vatexenumeration of the 75 official codes is replaced by"pattern": "^VATEX-[A-Z]{2}(-[A-Z0-9]+)+$", so that profile-specific codes such as the FrenchVATEX-FR-CGI*ones are accepted. Schematrons own the allowed list per profile.catalogues/cef, plus a case in the EN16931 addon for a country code passing validation.Pre-Review Checklist
go generate .to ensure that the Schemas and Regime data are up to date.And if you are part of the org: