Skip to content

feat(regimes): Add Andorra regime#730

Open
NicoGonMu wants to merge 7 commits intoinvopop:mainfrom
NicoGonMu:add-andorra-regime
Open

feat(regimes): Add Andorra regime#730
NicoGonMu wants to merge 7 commits intoinvopop:mainfrom
NicoGonMu:add-andorra-regime

Conversation

@NicoGonMu
Copy link

@NicoGonMu NicoGonMu commented Feb 24, 2026

Add Andorra regime

  • Add the regime from template.
  • Added the 5 tax category rates.
  • Added credit note and debit note correction methods.
  • Added validation for NRT (Andorra tax identification number).
  • Verified examples are correctly generated running both:
    a. gobl.exe build -i -e examples\ad\credit-note.yaml > examples\ad\out\credit-note.json".
    b. go test -run TestConvertExamplesToJSON -v -update.
  • Used .go generate . to populate the Regime data.
  • Ensured 100% test coverage.

Warning

Given the ongoing PR #736, I decided to remove the README file entirely and move what was in there to the Description field in the regime. The sources are also included in the description, so it will be convenient to move them to the new field once the changes in #736 are merged.

Pre-Review Checklist

  • Opened this PR as a draft
  • Read the CONTRIBUTING.md guide.
  • Performed a self-review of my code.
  • Added thorough tests with at least 90% code coverage.
  • Modified or created example GOBL documents to show my changes in use, if appropriate.
  • Added links to the source of the changes in tax regimes or addons, either structured or in the comments.
  • Run go generate . to ensure that the Schemas and Regime data are up to date.
  • Reviewed and fixed all linter warnings.
  • Been obsessive with pointer nil checks to avoid panics.
  • Updated the CHANGELOG.md with an overview of my changes.
  • Requested a review from Copilot and fixed or dismissed (with a reason) all the feedback raised.

Only after checking off all the previous items:

  • Marked this PR as ready for review and requested one from @samlown.

@NicoGonMu NicoGonMu marked this pull request as ready for review February 24, 2026 11:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Andorra (AD) tax regime to the GOBL regimes catalogue, including VAT/IGI rate definitions, invoice constraints, tax identity validation/normalization behavior, and accompanying examples and generated regime data.

Changes:

  • Register the new ad regime and provide its tax.RegimeDef (metadata, corrections, scenarios).
  • Add Andorra VAT/IGI tax category + rates, plus invoice and NRT (tax ID) validation logic.
  • Add Andorra examples and generated data/regimes/ad.json, and adjust an existing “unknown regime” invoice test.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
regimes/regimes.go Registers the new ad regime via blank import.
regimes/ad/ad.go Defines the Andorra RegimeDef, hooks validator/normalizer, and sets corrections/scenarios.
regimes/ad/invoices.go Adds regime-specific invoice validation (supplier tax ID required).
regimes/ad/tax_categories.go Defines Andorra VAT/IGI category with rates and sources.
regimes/ad/tax_identity.go Adds NRT validation via regexp-based code check.
regimes/ad/ad_test.go Tests regime construction, invoice validation, tax categories, validate/normalize entrypoints.
regimes/ad/tax_identity_test.go Unit tests for NRT validation patterns.
examples/ad/invoice.yaml Adds an Andorra invoice example input.
examples/ad/credit-note.yaml Adds an Andorra credit note example input.
examples/ad/out/invoice.json Generated JSON output for the invoice example.
examples/ad/out/credit-note.json Generated JSON output for the credit note example.
data/regimes/ad.json Generated regime data for Andorra.
bill/invoice_test.go Updates “unknown regime” test to use a different country code.
CHANGELOG.md Adds changelog entry for the new Andorra regime.

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

Copy link
Collaborator

@samlown samlown left a comment

Choose a reason for hiding this comment

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

Good first attempt. I think the naming of the tax category is important to re-consider. A comment that mentions the lack of a checksum in the Tax ID and a source for potential changes would be useful for tax IDs.

return validation.ValidateStruct(p,
validation.Field(&p.TaxID,
validation.Required,
tax.RequireIdentityCode,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this always the case? There may be a threshold for VAT related IDs.

Copy link
Author

Choose a reason for hiding this comment

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

AFAIK all invoices must include the NRT, regardless of turnover, if that's what you mean.

//
return []*tax.CategoryDef{
{
Code: tax.CategoryVAT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this one would need to be checked as the name in English is General Indirect Tax and not Value Added Tax. While it appears to be the same functionally wise, I don't think its totally compatible.

Copy link
Author

Choose a reason for hiding this comment

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

I think this is actually a VAT, despite the translation. It is a tax added to any goods or services sold. Like IVA in Spain. I would consider it a VAT, unless there's something else I'm missing. As per how's described in the official website: "The IGI is the tax that levies consumption by taxing the deliveries of goods and the provision of services carried out by businessmen or professionals, as well as the imports of goods.".

Comment on lines +26 to +29
validation.Field(&t.Code,
validation.Required,
validation.Match(nrtRegexp),
),
Copy link
Collaborator

Choose a reason for hiding this comment

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

No checksum validation is available here? This alternative implementation doesn't appear to define one either: https://github.com/ltns35/go-vat/blob/main/countries/andorra.go

Copy link
Author

Choose a reason for hiding this comment

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

No checksum is used. There are many sources that explain different rules for the NRT, but none of them official. What I did is taking the most commonly mentioned rules. I can see that the alternative implementation you mentioned has implemented some rules linking the first letter with the number; this is something I've only seen mentioned in this document that quotes stuff from 2014/15, and has all the reference links broken, so I simply didn't consider it reliable.

On top of that, I had a phone call with the Andorra Tax Agency, and they told me no algorithm is used for creating the NRTs. The only rules they mention is the letters F A E and L.

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.

3 participants