added croatia regime#724
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive support for the Croatian (HR) tax regime to GOBL, including VAT rate definitions, OIB (Personal Identification Number) validation, and example documents.
Changes:
- Added Croatian tax regime with EUR currency, VAT tax scheme, and Europe/Zagreb timezone
- Implemented OIB identity validation using ISO 7064 MOD 11.10 checksum algorithm
- Defined four VAT rates (25%, 13%, 5%, 0%) with references to official Croatian Tax Administration sources
- Included comprehensive test coverage for regime, identity, and tax identity validation
- Added example invoice and credit note documents with generated JSON outputs
Reviewed changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| regimes/regimes.go | Registered HR regime package in correct alphabetical order |
| regimes/hr/hr.go | Main regime definition with validator and normalizer functions |
| regimes/hr/identities.go | OIB identity type definition and validation setup |
| regimes/hr/identities_test.go | Comprehensive tests for OIB identity validation including edge cases |
| regimes/hr/tax_identity.go | OIB tax code validation with ISO 7064 MOD 11.10 checksum algorithm |
| regimes/hr/tax_identity_test.go | Tests for tax identity validation and normalization with valid/invalid checksums |
| regimes/hr/tax_categories.go | VAT category definitions with four rate tiers and Croatian translations |
| regimes/hr/hr_test.go | Regime initialization and validation tests |
| regimes/hr/README.md | Documentation of Croatian tax regime including OIB format and VAT rates |
| examples/hr/invoice-hr-hr.yaml | Example standard invoice with VAT and discounts |
| examples/hr/credit-note.yaml | Example credit note referencing preceding invoice |
| examples/hr/out/invoice-hr-hr.json | Generated and calculated invoice output |
| examples/hr/out/credit-note.json | Generated and calculated credit note output |
| data/schemas/tax/regime-code.json | Added HR to regime code schema in correct alphabetical position |
| data/regimes/hr.json | Generated regime data file with complete VAT category definitions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
samlown
left a comment
There was a problem hiding this comment.
Solid and concise first attempt. A few considerations regarding tax rate and documentation.
| }, | ||
| { | ||
| Keys: []cbc.Key{tax.KeyStandard}, | ||
| Rate: tax.RateZero, |
There was a problem hiding this comment.
Zero rate VAT has its own key now.
| Name: i18n.String{ | ||
| i18n.EN: "Croatia", | ||
| i18n.HR: "Hrvatska", | ||
| }, |
There was a problem hiding this comment.
I'd suggest moving some of the details from the README to here so that the details are available in the generated schema.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { | ||
| Keys: []cbc.Key{tax.KeyStandard}, | ||
| Rate: tax.RateZero, | ||
| Name: i18n.String{ | ||
| i18n.EN: "Zero Rate", | ||
| i18n.HR: "Nulta stopa", | ||
| }, | ||
| Values: []*tax.RateValueDef{ | ||
| { | ||
| Percent: num.MakePercentage(0, 3), | ||
| Since: cal.NewDate(2013, 7, 17), | ||
| }, | ||
| }, | ||
| }, |
There was a problem hiding this comment.
The VAT category defines a RateDef with Rate: tax.RateZero under Keys: []cbc.Key{tax.KeyStandard}. In this codebase, VAT “zero” is generally modeled via the zero key (tax.KeyZero) and tax.Combo.Normalize migrates Rate == "zero" into KeyZero and clears the rate. Keeping RateZero here is confusing (rate/key collision) and likely unused after normalization; consider removing this RateZero RateDef and rely on the global zero key instead (or, if you really need an explicit rate, ensure it’s associated with tax.KeyZero and won’t be normalized away).
| { | |
| Keys: []cbc.Key{tax.KeyStandard}, | |
| Rate: tax.RateZero, | |
| Name: i18n.String{ | |
| i18n.EN: "Zero Rate", | |
| i18n.HR: "Nulta stopa", | |
| }, | |
| Values: []*tax.RateValueDef{ | |
| { | |
| Percent: num.MakePercentage(0, 3), | |
| Since: cal.NewDate(2013, 7, 17), | |
| }, | |
| }, | |
| }, |
| ) | ||
|
|
||
| // validateTaxIdentity checks to ensure the Croatian OIB tax code is valid. | ||
| func validateTaxIdentity(tID *tax.Identity) error { |
There was a problem hiding this comment.
validateTaxIdentity will panic if tID is a typed-nil *tax.Identity (e.g., passed through hr.Validate as an any interface), because it takes &tID.Code unconditionally. Add a nil guard at the start of validateTaxIdentity (or in Validate before calling it) to ensure regime validation cannot panic on nil inputs.
| func validateTaxIdentity(tID *tax.Identity) error { | |
| func validateTaxIdentity(tID *tax.Identity) error { | |
| if tID == nil { | |
| return nil | |
| } |
Added a new Croatia (HR) tax regime, generated regime data and added example documents.
Changes
regimes.goto import the new hr package so the regime is registered automatically.examples/hr, including standard invoice with VAT and credit note referencing a preceding invoice.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: