Skip to content

Commit

Permalink
IT: Refactor fiscal code to party identities
Browse files Browse the repository at this point in the history
  • Loading branch information
samlown committed Jul 11, 2024
1 parent a86f131 commit daa9c2b
Show file tree
Hide file tree
Showing 26 changed files with 877 additions and 260 deletions.
15 changes: 8 additions & 7 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/setup-go@v4
with:
go-version: "1.18"
cache: false

- name: Check out code
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: "go.mod"
id: go

- name: Lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v2
with:
version: v1.55
version: v1.58
16 changes: 0 additions & 16 deletions .golangci.toml

This file was deleted.

30 changes: 30 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
run:
timeout: "120s"

output:
formats:
- format: "colored-line-number"

linters:
enable:
- "gocyclo"
- "unconvert"
- "goimports"
- "govet"
#- "misspell" # doesn't handle multilanguage well
- "nakedret"
- "revive"
- "goconst"
- "unparam"
- "gofmt"
- "errname"
- "zerologlint"

linters-settings:
staticcheck:
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: ["all"]

issues:
exclude-use-default: false
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to GOBL will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). See also the [GOBL versions](https://docs.gobl.org/overview/versions) documentation site for more details.

## [vX.XX.X] - XXXX-XX-XX

### Changed

- IT: moved fiscal code (codice fiscale) from the `org.Party` Tax ID to the Identities array with the specific key `it-fiscal-code`. This implies that invoices can now be issued with **both** a VAT code (partita IVA) and a fiscal code (codice fiscale).
- IT: data will be normalized automatically to move the fiscal code from the tax ID to the identities array.

## [v0.80.1] - 2024-07-11

### Added
Expand All @@ -13,7 +20,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

### Changed

- GB: removed requirement for suppliers to have a tax ID code (country is still requried!)
- GB: removed requirement for suppliers to have a tax ID code (country is still required!)

## [v0.80.0] - 2024-06-27

Expand Down
4 changes: 2 additions & 2 deletions currency/def.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func WithDisambiguateSymbol() FormatOption {
// WithNumeralSystem will override the default numeral system used to output
// numbers.
func WithNumeralSystem(ns num.NumeralSystem) FormatOption {
return func(d *Def, f num.Formatter) num.Formatter {
return func(_ *Def, f num.Formatter) num.Formatter {
f.NumeralSystem = ns
return f
}
Expand Down Expand Up @@ -165,7 +165,7 @@ func (ds *defs) load(src fs.FS, root string) error {
ds.byPriority = make([]*Def, 0)
ds.byCode = make(map[Code]*Def)

err := fs.WalkDir(src, root, func(path string, d fs.DirEntry, err error) error {
err := fs.WalkDir(src, root, func(path string, _ fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("walking directory: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Error struct {

// FieldErrors is a map of field names to errors, which is provided when it
// was possible to determine that the error was related to a specific field.
type FieldErrors map[string]error
type FieldErrors map[string]error // nolint:errname

var (
// ErrNoDocument is provided when the envelope does not contain a
Expand Down
2 changes: 1 addition & 1 deletion examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var updateExamples = flag.Bool("update", false, "Update the examples in the repo
func TestConvertExamplesToJSON(t *testing.T) {
// Find all .yaml files in subdirectories
var files []string
err := filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
err := filepath.Walk("./", func(path string, _ os.FileInfo, _ error) error {
switch filepath.Ext(path) {
case ".yaml", ".json":
for _, skip := range skipExamplePaths {
Expand Down
12 changes: 11 additions & 1 deletion org/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,24 @@ func IdentityForType(in []*Identity, typ cbc.Code) *Identity {
return nil
}

// IdentityForKey helps return the identity with a matching key.
func IdentityForKey(in []*Identity, key cbc.Key) *Identity {
for _, v := range in {
if v.Key == key {
return v
}
}
return nil
}

// AddIdentity makes it easier to add a new identity to a list and replace an
// existing value with a matching type.
func AddIdentity(in []*Identity, i *Identity) []*Identity {
if in == nil {
return []*Identity{i}
}
for _, v := range in {
if v.Type == i.Type {
if v.Type == i.Type || v.Key == i.Key {
*v = *i // copy in place
return in
}
Expand Down
8 changes: 8 additions & 0 deletions org/party.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ func (p *Party) Calculate() error {
if r == nil {
return nil // nothing to do here
}

// Normalize identities explicitly
for _, id := range p.Identities {
if err := r.CalculateObject(id); err != nil {
return err
}
}

return r.CalculateObject(p)
}

Expand Down
5 changes: 3 additions & 2 deletions regimes/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ const (
)

var (
taxCodeBadCharsRegexp = regexp.MustCompile(`[^A-Z0-9]+`)
// TaxCodeBadCharsRegexp is used to remove any characters that are not valid in a tax code.
TaxCodeBadCharsRegexp = regexp.MustCompile(`[^A-Z0-9]+`)
)

// NormalizeTaxIdentity removes any whitespace or separation characters and ensures all letters are
// uppercase.
func NormalizeTaxIdentity(tID *tax.Identity) error {
code := strings.ToUpper(tID.Code.String())
code = taxCodeBadCharsRegexp.ReplaceAllString(code, "")
code = TaxCodeBadCharsRegexp.ReplaceAllString(code, "")
code = strings.TrimPrefix(code, string(tID.Country))
tID.Code = cbc.Code(code)
return nil
Expand Down
96 changes: 96 additions & 0 deletions regimes/it/examples/hotel-b2c.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"$schema": "https://gobl.org/draft-0/bill/invoice",
"uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0",
"series": "SAMPLE",
"code": "002",
"currency": "EUR",
"issue_date": "2023-05-21",
"tax": {
"prices_include": "VAT"
},
"type": "standard",
"supplier": {
"tax_id": {
"country": "IT",
"code": "12345678903"
},
"name": "Hotel California",
"registration": {
"capital": "50000.00",
"currency": "EUR",
"entry": "123456",
"office": "RM"
},
"addresses": [
{
"num": "102",
"street": "Via California",
"locality": "Palermo",
"region": "PA",
"code": "33213",
"country": "IT"
}
]
},
"customer": {
"tax_id": {
"country": "IT",
"type": "individual",
"code": "RSSGNN60R30H501U"
},
"name": "Mela S.r.l.",
"inboxes": [
{
"key": "it-sdi-code",
"code": "M5UXCR5"
}
],
"addresses": [
{
"num": "23",
"street": "Via dei Mille",
"locality": "Firenze",
"region": "FI",
"code": "00100",
"country": "IT"
}
]
},
"lines": [
{
"i": 1,
"quantity": "1",
"item": {
"name": "Tassa di Soggiorno",
"price": "1.00"
},
"taxes": [
{
"cat": "VAT",
"rate": "exempt",
"ext": {
"it-sdi-nature": "N4"
}
}
],
"sum": "1.00",
"total": "1.00"
},
{
"i": 2,
"quantity": "1",
"item": {
"name": "Camera Matrimoniale",
"price": "125.00"
},
"taxes": [
{
"cat": "VAT",
"rate": "intermediate"
}
],
"sum": "125.00",
"total": "137.50"
}
]
}
98 changes: 98 additions & 0 deletions regimes/it/examples/hotel-b2g.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
{
"$schema": "https://gobl.org/draft-0/bill/invoice",
"uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0",
"series": "SAMPLE",
"code": "002",
"currency": "EUR",
"issue_date": "2023-05-21",
"tax": {
"prices_include": "VAT",
"ext": {
"it-sdi-format": "FPA12"
}
},
"type": "standard",
"supplier": {
"tax_id": {
"country": "IT",
"code": "12345678903"
},
"name": "Hotel California",
"registration": {
"capital": "50000.00",
"currency": "EUR",
"entry": "123456",
"office": "RM"
},
"addresses": [
{
"num": "102",
"street": "Via California",
"locality": "Palermo",
"region": "PA",
"code": "33213",
"country": "IT"
}
]
},
"customer": {
"tax_id": {
"country": "IT",
"code": "13029381004"
},
"name": "Mela S.r.l.",
"inboxes": [
{
"key": "it-sdi-code",
"code": "M5UXCR5"
}
],
"addresses": [
{
"num": "23",
"street": "Via dei Mille",
"locality": "Firenze",
"region": "FI",
"code": "00100",
"country": "IT"
}
]
},
"lines": [
{
"i": 1,
"quantity": "1",
"item": {
"name": "Tassa di Soggiorno",
"price": "1.00"
},
"taxes": [
{
"cat": "VAT",
"rate": "exempt",
"ext": {
"it-sdi-nature": "N4"
}
}
],
"sum": "1.00",
"total": "1.00"
},
{
"i": 2,
"quantity": "1",
"item": {
"name": "Camera Matrimoniale",
"price": "125.00"
},
"taxes": [
{
"cat": "VAT",
"rate": "intermediate"
}
],
"sum": "125.00",
"total": "137.50"
}
]
}
Loading

0 comments on commit daa9c2b

Please sign in to comment.