Add Norway (NO) tax regime#728
Conversation
|
@samlown could you please request a review from Copilot? 🙏 |
There was a problem hiding this comment.
Pull request overview
Adds Norway (NO) as a first-class tax regime in GOBL, including VAT rate definitions, identity normalization/validation, and invoice-specific validation/scenario behavior, plus generated schema/data and example fixtures.
Changes:
- Register new
NOregime and implement Norwegian VAT category/rates (incl. historical values), invoice tags/scenarios, and correction support. - Add Norwegian identity support: organisasjonsnummer (
org.IdentitytypeON) and tax identity normalization/validation (mod-11). - Add tests + example documents/JSON snapshots, and update generated regime/schema data + changelog.
- (Also introduces repo-level agent/tooling files: Makefile,
.claude/,agent_docs/,CLAUDE.md.)
Reviewed changes
Copilot reviewed 29 out of 35 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
regimes/regimes.go |
Registers the new Norway regime via blank import. |
regimes/no/no.go |
Defines and registers the NO tax.RegimeDef (currency, VAT scheme, validator/normalizer, tags, scenarios, corrections). |
regimes/no/tax_categories.go |
VAT category + four rates with historical values and bilingual labels/sources. |
regimes/no/tax_identity.go |
Tax identity normalization (strip NO + MVA) and mod-11 validation. |
regimes/no/identities.go |
Adds org identity type ON + normalization/validation using same mod-11 logic. |
regimes/no/invoices.go |
Norway-specific invoice validation rules (supplier requirements, customer name, preceding refs for credit/debit). |
regimes/no/scenarios.go |
Adds foretaksregisteret tag + scenario note injection (and reverse-charge note). |
regimes/no/*_test.go |
Coverage for normalization/validation, scenarios, and invoice calc/validation behaviors. |
regimes/no/README.md |
Regime documentation (rates, identities, tags, scope). |
examples/no/*.yaml + examples/no/out/*.json |
Example invoices and expected calculated envelopes/snapshots. |
data/schemas/tax/regime-code.json |
Adds NO to regime-code schema enum. |
data/regimes/no.json |
Generated serialized regime definition for NO. |
CHANGELOG.md |
Notes addition of Norwegian regime in Unreleased. |
Makefile |
Adds dev workflow targets (build/test/generate/lint/etc.) using .claude/scripts/run_silent.sh. |
.claude/settings.local.json |
Adds Claude session hooks/plugins (appears local/developer-specific). |
.claude/scripts/* |
Adds helper scripts used by Makefile and Claude context gathering. |
agent_docs/* + CLAUDE.md |
Adds agent-facing documentation and repo patterns/checklists. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
samlown
left a comment
There was a problem hiding this comment.
Solid first attempt. There are a few things I'd remove before accepting the PR in order to be more usable. Support for simplified invoices is usually a requirement.
- Add simplified invoice support: TagSimplified check, customer Empty, relaxed supplier validation - Relax supplier TaxID requirement: optional for non-VAT-registered companies below NOK 50,000 turnover - Conditional supplier address: required for standard, optional for simplified invoices - Remove TestInvoiceCalculation and redundant calculation assertions - Add Description field to regime definition using here.Doc - Remove foretaksregisteret tag, constant, scenario, TagSet, and all related tests and examples - Add simplified invoice example and dedicated test cases - Update README.md and CHANGELOG.md to reflect changes - Change invoiceScenarios from func to var for FR/DE/IT consistency - Regenerate data/regimes/no.json
Thank you 🙏 @samlown. I’ve addressed the comments, and I really enjoyed thinking through what it takes to support a new e-invoicing regime (sources of truth, regulatory changes, company types, etc.). |
samlown
left a comment
There was a problem hiding this comment.
This looks great! Thanks! Only change would be to relax the customer not-present check, then happy to merge 👍
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #728 +/- ##
==========================================
+ Coverage 93.05% 93.08% +0.03%
==========================================
Files 333 337 +4
Lines 17785 17945 +160
==========================================
+ Hits 16549 16704 +155
- Misses 870 872 +2
- Partials 366 369 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Add simplified invoice support: TagSimplified check, customer Empty, relaxed supplier validation - Relax supplier TaxID requirement: optional for non-VAT-registered companies below NOK 50,000 turnover - Conditional supplier address: required for standard, optional for simplified invoices - Remove TestInvoiceCalculation and redundant calculation assertions - Add Description field to regime definition using here.Doc - Remove foretaksregisteret tag, constant, scenario, TagSet, and all related tests and examples - Add simplified invoice example and dedicated test cases - Update README.md and CHANGELOG.md to reflect changes - Change invoiceScenarios from func to var for FR/DE/IT consistency - Regenerate data/regimes/no.json
Implements complete support for Norway's VAT tax regime with: - VAT categories and rates (standard 25%, reduced 15%, super-reduced 12%, special 11.11%) - Organisasjonsnummer (org.Identity type ON) with mod-11 validation - Tax identity normalization stripping NO prefix and MVA suffix - Support for reverse-charge and foretaksregisteret tagging with legal notes - Invoice validation requiring supplier name/address/tax ID and customer name - Credit note and debit note correction types with preceding doc reference - Norwegian (nb) translation support alongside English - Comprehensive tests with edge case coverage - Example fixtures: standard invoice, credit note, debit note, reverse-charge Sources: - Skatteetaten VAT rates: https://www.skatteetaten.no/en/rates/vat/ - Brønnøysundregistrene org.nr: https://www.brreg.no/en/about-us-2/our-registers/ - Merverdiavgiftsloven: https://lovdata.no/dokument/NL/lov/2009-06-19-58
Add bilingual descriptions to general rate and foretaksregisteret tag, historical super-reduced rate values (COVID reduction, 2012 increase), fix special rate Since date to 2009, and add standard and multi-rate example invoices.
Fix super-reduced rate history (wrong dates, missing intermediate rates) and add pre-2005 history for general and reduced rates based on Stortinget resolutions and NOU 2019:11. Add calculation verification tests for standard, tax-inclusive, and multi-rate invoices, plus reverse-charge exempt scenario test.
- Add simplified invoice support: TagSimplified check, customer Empty, relaxed supplier validation - Relax supplier TaxID requirement: optional for non-VAT-registered companies below NOK 50,000 turnover - Conditional supplier address: required for standard, optional for simplified invoices - Remove TestInvoiceCalculation and redundant calculation assertions - Add Description field to regime definition using here.Doc - Remove foretaksregisteret tag, constant, scenario, TagSet, and all related tests and examples - Add simplified invoice example and dedicated test cases - Update README.md and CHANGELOG.md to reflect changes - Change invoiceScenarios from func to var for FR/DE/IT consistency - Regenerate data/regimes/no.json
Add tax authority source references following the upstream clean-regimes pattern (Skatteetaten, Brønnøysundregistrene, Lovdata) and regenerate schema and regime JSON to include NO in the $defs format.
|
@samlown comments addressed 👌 |
Add full Norwegian tax regime implementation, including VAT support, organisasjonsnummer validation, simplified invoice handling, and invoice type handling.
ON) with mod-11 check digit validation per Brønnøysundregistrene specNOprefix andMVAsuffixhere.Doc(following FR pattern)Sources
Out of Scope
Deliberately excluded from this PR (documented in README):
Pre-Review Checklist
go generate .to ensure that the Schemas and Regime data are up to date.Only after checking off all the previous items: