Skip to content

Commit

Permalink
Merge pull request #25 from invopop/iva-code-fixes
Browse files Browse the repository at this point in the history
Fixing IVA tax codes for individuals and foreign business
  • Loading branch information
samlown authored Feb 14, 2024
2 parents 757dde7 + 79a431b commit 627373c
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v1
with:
go-version: "1.20.4"
go-version: "1.21.5"
id: go

- name: Check out code
Expand Down
14 changes: 12 additions & 2 deletions address.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package fatturapa

import (
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/org"
)

const (
foreignCAP = "00000"
)

// address from IndirizzoType
type address struct {
Indirizzo string // Street
Expand All @@ -15,14 +20,19 @@ type address struct {
}

func newAddress(addr *org.Address) *address {
return &address{
ad := &address{
Indirizzo: addressStreet(addr),
NumeroCivico: addr.Number,
CAP: addr.Code,
Comune: addr.Locality,
Provincia: addr.Region,
Nazione: addr.Country.String(),
}
if addr.Country == l10n.IT {
ad.CAP = addr.Code
} else {
ad.CAP = foreignCAP
}
return ad
}

func addressStreet(address *org.Address) string {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module github.com/invopop/gobl.fatturapa

go 1.19
go 1.20

require (
github.com/invopop/gobl v0.67.0
github.com/invopop/gobl v0.67.3
github.com/invopop/xmldsig v0.8.0
github.com/magefile/mage v1.14.0
github.com/spf13/cobra v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/gobl v0.67.0 h1:9c28iBunAWYUILIMGkx1zFH/cC5srH5wp9pAb4223MA=
github.com/invopop/gobl v0.67.0/go.mod h1:Jau+ajdfUCBPVH9VMor6aeYq3S9o7HuSNm07QxxxomE=
github.com/invopop/gobl v0.67.3 h1:My3e65q+ERZVBEtksjV3nMs5nw+wlOohe8Jptf6vKwA=
github.com/invopop/gobl v0.67.3/go.mod h1:Jau+ajdfUCBPVH9VMor6aeYq3S9o7HuSNm07QxxxomE=
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/invopop/validation v0.3.0 h1:o260kbjXzoBO/ypXDSSrCLL7SxEFUXBsX09YTE9AxZw=
Expand Down
5 changes: 2 additions & 3 deletions items.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"strconv"

"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/i18n"
"github.com/invopop/gobl/regimes/it"
"github.com/invopop/gobl/tax"
Expand Down Expand Up @@ -119,9 +118,9 @@ func extractLinePriceAdjustments(line *bill.Line) []*scontoMaggiorazione {
func findRiferimentoNormativo(rateTotal *tax.RateTotal) string {
def := regime.ExtensionDef(it.ExtKeySDINature)

nature := rateTotal.Ext[it.ExtKeySDINature]
nature := rateTotal.Ext[it.ExtKeySDINature].Code()
for _, c := range def.Codes {
if c.Code == cbc.Code(nature) {
if c.Code == nature {
return c.Name[i18n.IT]
}
}
Expand Down
20 changes: 12 additions & 8 deletions parties.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
)

const (
statoLiquidazioneDefault = "LN"
euCitizenTaxCodeDefault = "0000000"
nonEUCitizenTaxCodeDefault = "99999999999"
statoLiquidazioneDefault = "LN"
nonITCitizenTaxCodeDefault = "0000000"
nonEUBusinessTaxCodeDefault = "OO99999999999"
)

type supplier struct {
Expand Down Expand Up @@ -111,10 +111,8 @@ func newCessionarioCommittente(c *org.Party) *customer {
if c.TaxID != nil {
if isCodiceFiscale(c.TaxID) {
da.CodiceFiscale = c.TaxID.Code.String()
} else if isEUCountry(c.TaxID.Country) {
da.IdFiscaleIVA = customerFiscaleIVA(c.TaxID, euCitizenTaxCodeDefault)
} else {
da.IdFiscaleIVA = customerFiscaleIVA(c.TaxID, nonEUCitizenTaxCodeDefault)
da.IdFiscaleIVA = customerFiscaleIVA(c.TaxID)
}
}

Expand Down Expand Up @@ -153,11 +151,17 @@ func newContatti(party *org.Party) *contatti {
return c
}

func customerFiscaleIVA(id *tax.Identity, fallBack string) *taxID {
func customerFiscaleIVA(id *tax.Identity) *taxID {
idCodice := id.Code.String()

if idCodice == "" {
idCodice = fallBack
// Assume private individual
idCodice = nonITCitizenTaxCodeDefault
} else {
// Must be a company with a local tax ID
if !isEUCountry(id.Country) {
idCodice = nonEUBusinessTaxCodeDefault
}
}

return &taxID{
Expand Down
6 changes: 3 additions & 3 deletions parties_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func TestPartiesCustomer(t *testing.T) {
assert.Equal(t, "0000000", c.DatiAnagrafici.IdFiscaleIVA.IdCodice)
})

t.Run("should contain customer info for non-EU citizen with Tax ID given", func(t *testing.T) {
t.Run("should replace customer ID info for non-EU citizen with Tax ID given", func(t *testing.T) {
env := test.LoadTestFile("invoice-simple.json")
test.ModifyInvoice(env, func(inv *bill.Invoice) {
inv.Customer.TaxID.Code = "09823876432"
Expand All @@ -129,7 +129,7 @@ func TestPartiesCustomer(t *testing.T) {
c := doc.FatturaElettronicaHeader.CessionarioCommittente

assert.Equal(t, "GB", c.DatiAnagrafici.IdFiscaleIVA.IdPaese)
assert.Equal(t, "09823876432", c.DatiAnagrafici.IdFiscaleIVA.IdCodice)
assert.Equal(t, "OO99999999999", c.DatiAnagrafici.IdFiscaleIVA.IdCodice)
})

t.Run("should contain customer info for non-EU citizen with no Tax ID given", func(t *testing.T) {
Expand All @@ -145,7 +145,7 @@ func TestPartiesCustomer(t *testing.T) {
c := doc.FatturaElettronicaHeader.CessionarioCommittente

assert.Equal(t, "JP", c.DatiAnagrafici.IdFiscaleIVA.IdPaese)
assert.Equal(t, "99999999999", c.DatiAnagrafici.IdFiscaleIVA.IdCodice)
assert.Equal(t, "0000000", c.DatiAnagrafici.IdFiscaleIVA.IdCodice)
})

t.Run("should not fail if missing key data", func(t *testing.T) {
Expand Down
141 changes: 141 additions & 0 deletions test/data/invoice-hotel-private.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"$schema": "https://gobl.org/draft-0/envelope",
"head": {
"uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6",
"dig": {
"alg": "sha256",
"val": "AAAA"
}
},
"doc": {
"$schema": "https://gobl.org/draft-0/bill/invoice",
"type": "standard",
"series": "SAMPLE",
"code": "003",
"issue_date": "2023-05-21",
"currency": "EUR",
"tax": {
"prices_include": "VAT"
},
"supplier": {
"name": "Hotel California",
"tax_id": {
"country": "IT",
"code": "12345678903"
},
"addresses": [
{
"num": "102",
"street": "Via California",
"locality": "Palermo",
"region": "PA",
"code": "33213",
"country": "IT"
}
],
"registration": {
"currency": "EUR",
"office": "RM",
"entry": "123456"
}
},
"customer": {
"name": "Random Person",
"tax_id": {
"country": "GB"
},
"addresses": [
{
"num": "23",
"street": "Main Street",
"locality": "London",
"code": "W1 A2",
"country": "GB"
}
]
},
"lines": [
{
"i": 1,
"quantity": "1",
"item": {
"name": "Tassa di Soggiorno",
"price": "1.00"
},
"sum": "1.00",
"taxes": [
{
"cat": "VAT",
"rate": "exempt",
"ext": {
"it-sdi-nature": "N1"
}
}
],
"total": "1.00"
},
{
"i": 2,
"quantity": "1",
"item": {
"name": "Camera Matrimoniale",
"price": "125.00"
},
"sum": "125.00",
"taxes": [
{
"cat": "VAT",
"rate": "intermediate",
"percent": "10.0%"
}
],
"total": "125.00"
}
],
"payment": {
"advances": [
{
"date": "2023-05-01",
"key": "card",
"desc": "deposit",
"amount": "29.00"
}
]
},
"totals": {
"sum": "126.00",
"tax_included": "11.36",
"total": "114.64",
"taxes": {
"categories": [
{
"code": "VAT",
"rates": [
{
"key": "exempt",
"ext": {
"it-sdi-nature": "N1"
},
"base": "1.00",
"amount": "0.00"
},
{
"key": "intermediate",
"base": "113.6364",
"percent": "10.0%",
"amount": "11.3636"
}
],
"amount": "11.3636"
}
],
"sum": "11.3636"
},
"tax": "11.36",
"total_with_tax": "126.00",
"payable": "126.00",
"advance": "29.00",
"due": "97.00"
}
}
}

0 comments on commit 627373c

Please sign in to comment.