diff --git a/.gitignore b/.gitignore index 407cd06..9707ec2 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ # ENV files .env + +/gobl.fatturapa diff --git a/README.md b/README.md index 62fe568..9e6a283 100644 --- a/README.md +++ b/README.md @@ -123,10 +123,10 @@ converter := fatturapa.NewConverter( ### CLI -The command line interface can be useful for situations when you're using a language other than Golang in your application. Install with: +The command line interface can be useful for situations when you're using a language other than Golang in your application. Download one of the [pre-compiled `gobl.fatturapa` releases](https://github.com/invopop/gobl.fatturapa/releases) or install with: ```bash -go install github.com/invopop/gobl.fatturapa +go install github.com/invopop/gobl.fatturapa/cmd/gobl.fatturapa ``` Simply provide the input GOBL JSON file and output to a file or another application: diff --git a/address.go b/address.go index 0517043..1fa1959 100644 --- a/address.go +++ b/address.go @@ -33,7 +33,7 @@ func newAddress(addr *org.Address) *Address { Region: addressRegion(addr), Country: addr.Country.String(), } - if addr.Country == l10n.IT { + if addr.Country == l10n.IT.ISO() { ad.Code = addr.Code } else { ad.Code = foreignCAP @@ -46,7 +46,7 @@ func newAddress(addr *org.Address) *Address { // or return an empty string to avoid FatturaPA validation issues. // The province is optional, so it's not a problem if it's not set. func addressRegion(address *org.Address) string { - if address.Country == l10n.IT { + if address.Country == l10n.IT.ISO() { if provinceRegexp.MatchString(address.Region) { return address.Region } diff --git a/address_test.go b/address_test.go index 9c187d3..6b7741b 100644 --- a/address_test.go +++ b/address_test.go @@ -3,7 +3,6 @@ package fatturapa import ( "testing" - "github.com/invopop/gobl/l10n" "github.com/invopop/gobl/org" "github.com/stretchr/testify/assert" ) @@ -16,7 +15,7 @@ func TestAddressRegion(t *testing.T) { Locality: "Roma", Region: "RM", Code: "00100", - Country: l10n.IT, + Country: "IT", } out := newAddress(addr) @@ -30,7 +29,7 @@ func TestAddressRegion(t *testing.T) { Locality: "Roma", Region: "Rome", Code: "00100", - Country: l10n.IT, + Country: "IT", } out := newAddress(addr) @@ -44,7 +43,7 @@ func TestAddressRegion(t *testing.T) { Locality: "London", Region: "RM", Code: "00100", - Country: l10n.GB, + Country: "GB", } out := newAddress(addr) diff --git a/body.go b/body.go index 2d45530..7a6e4eb 100644 --- a/body.go +++ b/body.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/bill" "github.com/invopop/gobl/cbc" "github.com/invopop/gobl/regimes/it" @@ -100,7 +101,7 @@ func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) { code := inv.Code if inv.Series != "" { - code = fmt.Sprintf("%s-%s", inv.Series, inv.Code) + code = cbc.Code(fmt.Sprintf("%s-%s", inv.Series, inv.Code)) } return &datiGenerali{ @@ -108,7 +109,7 @@ func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) { TipoDocumento: codeTipoDocumento, Divisa: string(inv.Currency), Data: inv.IssueDate.String(), - Numero: code, + Numero: code.String(), DatiRitenuta: dr, DatiBollo: newDatiBollo(inv.Charges), ImportoTotaleDocumento: formatAmount(&inv.Totals.Payable), @@ -119,14 +120,16 @@ func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) { } func findCodeTipoDocumento(inv *bill.Invoice) (string, error) { - ss := inv.ScenarioSummary() + if inv.Tax == nil { + return "", fmt.Errorf("missing tax") + } - code := ss.Codes[it.KeyFatturaPATipoDocumento] - if code == "" { - return "", fmt.Errorf("could not find TipoDocumento code") + val, ok := inv.Tax.Ext[sdi.ExtKeyDocumentType] + if !ok || val == "" { + return "", fmt.Errorf("missing %s", sdi.ExtKeyDocumentType) } - return code.String(), nil + return val.String(), nil } func newDatiBollo(charges []*bill.Charge) *datiBollo { diff --git a/cmd/gobl.fatturapa/convert.go b/cmd/gobl.fatturapa/convert.go index 630c2e3..8f05d8f 100644 --- a/cmd/gobl.fatturapa/convert.go +++ b/cmd/gobl.fatturapa/convert.go @@ -84,7 +84,7 @@ func loadConverterFromConfig(c *convertOpts) (*fatturapa.Converter, error) { countryCode := c.transmitter[:2] taxID := c.transmitter[2:] - code := l10n.CountryCode(countryCode) + code := l10n.TaxCountryCode(countryCode) err := code.Validate() if err != nil { return nil, fmt.Errorf("tax ID must be prefixed by a valid country code") diff --git a/eu.go b/eu.go index 29a426b..ca2dc58 100644 --- a/eu.go +++ b/eu.go @@ -2,7 +2,7 @@ package fatturapa import "github.com/invopop/gobl/l10n" -var euCountries = []l10n.CountryCode{ +var euCountries = []l10n.Code{ l10n.AT, // Austria l10n.BE, // Belgium l10n.BG, // Bulgaria @@ -32,7 +32,7 @@ var euCountries = []l10n.CountryCode{ l10n.SE, // Sweden } -func isEUCountry(c l10n.CountryCode) bool { +func isEUCountry(c l10n.Code) bool { for _, cc := range euCountries { if c == cc { return true diff --git a/go.mod b/go.mod index 4fcb73d..fd5bf8d 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,16 @@ module github.com/invopop/gobl.fatturapa -go 1.21 +go 1.22 -toolchain go1.22.1 +toolchain go1.22.5 require ( - github.com/invopop/gobl v0.81.0 + github.com/invopop/gobl v0.200.0-rc3 github.com/invopop/xmldsig v0.8.0 github.com/lestrrat-go/libxml2 v0.0.0-20240521004304-a75c203ac627 - github.com/magefile/mage v1.14.0 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.8.4 - gitlab.com/flimzy/testy v0.12.4 + gitlab.com/flimzy/testy v0.14.0 ) require ( @@ -25,17 +24,19 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/invopop/jsonschema v0.12.0 // indirect - github.com/invopop/validation v0.3.0 // indirect + github.com/invopop/validation v0.7.0 // indirect github.com/invopop/yaml v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/magefile/mage v1.15.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/otiai10/copy v1.10.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.26.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect software.sslmate.com/src/go-pkcs12 v0.2.0 // indirect ) + +// replace github.com/invopop/gobl => ../gobl diff --git a/go.sum b/go.sum index bf6dae0..cf40104 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,6 @@ cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= @@ -11,99 +10,98 @@ github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.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.81.0 h1:bFzXkiNCdjXZcTrggsM8bzeddPDwAk/sUxinK7jaSlQ= -github.com/invopop/gobl v0.81.0/go.mod h1:3ixShxX1jlOKo5Rw22HVQh3jXnK9AZa7Twcw7L92qn0= +github.com/invopop/gobl v0.200.0-rc3 h1:Y/sQMQHufdlNx5Jlx78bnrValco/JLIqA9WbJjbLi5M= +github.com/invopop/gobl v0.200.0-rc3/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU= 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= -github.com/invopop/validation v0.3.0/go.mod h1:qIBG6APYLp2Wu3/96p3idYjP8ffTKVmQBfKiZbw0Hts= +github.com/invopop/validation v0.7.0 h1:NBPLqvYGmLZLQuk5jh0PbaBBetJW7f2VEk/BTWJkGBU= +github.com/invopop/validation v0.7.0/go.mod h1:nLLeXYPGwUNfdCdJo7/q3yaHO62LSx/3ri7JvgKR9vg= github.com/invopop/xmldsig v0.8.0 h1:W/yRh/HcMSlZrkaVtIeycxmBLssXIfy437yNCvx4gD4= github.com/invopop/xmldsig v0.8.0/go.mod h1:dc3+2BYNw0vzauyZiOobTltp1t3BbvWSq7ae/F2gdk0= github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= -github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= +github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/lestrrat-go/libxml2 v0.0.0-20240521004304-a75c203ac627 h1:M7EEuhGDmn9bWSnap5mzVlg8pmVucmLytCjVjm+H4QU= github.com/lestrrat-go/libxml2 v0.0.0-20240521004304-a75c203ac627/go.mod h1:/0MMipmS+5SMXCSkulsvJwYmddKI4IL5tVy6AZMo9n0= -github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= -github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= +github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/otiai10/copy v1.10.0 h1:znyI7l134wNg/wDktoVQPxPkgvhDfGCYUasey+h0rDQ= -github.com/otiai10/copy v1.10.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= -github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= -github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.12.1-0.20240709150035-ccf4b4329d21 h1:igWZJluD8KtEtAgRyF4x6lqcxDry1ULztksMJh2mnQE= +github.com/rogpeppe/go-internal v1.12.1-0.20240709150035-ccf4b4329d21/go.mod h1:RMRJLmBOqWacUkmJHRMiPKh1S1m3PA7Zh4W80/kWPpg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 h1:wD1IWQwAhdWclCwaf6DdzgCAe9Bfz1M+4AHRd7N786Y= github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693/go.mod h1:6hSY48PjDm4UObWmGLyJE9DxYVKTgR9kbCspXXJEhcU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= -gitlab.com/flimzy/testy v0.12.4 h1:J2plNCG5d9FWfik30yOZrajcPrWbiDHrk0qw1nMstNU= -gitlab.com/flimzy/testy v0.12.4/go.mod h1:9wPR98kErJw1lrq/aIJ8UZ6A0Dn7CHU0T6Qx4b2FiyQ= +gitlab.com/flimzy/testy v0.14.0 h1:2nZV4Wa1OSJb3rOKHh0GJqvvhtE03zT+sKnPCI0owfQ= +gitlab.com/flimzy/testy v0.14.0/go.mod h1:m3aGuwdXc+N3QgnH+2Ar2zf1yg0UxNdIaXKvC5SlfMk= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/xmlpath.v1 v1.0.0-20140413065638-a146725ea6e7 h1:zibSPXbkfB1Dwl76rJgLa68xcdHu42qmFTe6vAnU4wA= gopkg.in/xmlpath.v1 v1.0.0-20140413065638-a146725ea6e7/go.mod h1:wo0SW5T6XqIKCCAge330Cd5sm+7VI6v85OrQHIk50KM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/items.go b/items.go index 17812ea..6ec65fb 100644 --- a/items.go +++ b/items.go @@ -3,9 +3,9 @@ package fatturapa import ( "strconv" + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/bill" "github.com/invopop/gobl/i18n" - "github.com/invopop/gobl/regimes/it" "github.com/invopop/gobl/tax" ) @@ -59,7 +59,7 @@ func generateLineDetails(inv *bill.Invoice) []*dettaglioLinee { vatTax := line.Taxes.Get(tax.CategoryVAT) if vatTax != nil { d.AliquotaIVA = formatPercentageWithZero(vatTax.Percent) - d.Natura = vatTax.Ext[it.ExtKeySDINature].String() + d.Natura = exemptExtensionCode(vatTax.Ext) } } @@ -69,6 +69,16 @@ func generateLineDetails(inv *bill.Invoice) []*dettaglioLinee { return dl } +func exemptExtensionCode(ext tax.Extensions) string { + if ext.Has(sdi.ExtKeyExempt) { + return ext[sdi.ExtKeyExempt].String() + } + if ext.Has("it-sdi-nature") { // old key + return ext["it-sdi-nature"].String() + } + return "" +} + func generateTaxSummary(inv *bill.Invoice) []*datiRiepilogo { var dr []*datiRiepilogo var vatRateTotals []*tax.RateTotal @@ -83,7 +93,7 @@ func generateTaxSummary(inv *bill.Invoice) []*datiRiepilogo { for _, rateTotal := range vatRateTotals { dr = append(dr, &datiRiepilogo{ AliquotaIVA: formatPercentageWithZero(rateTotal.Percent), - Natura: rateTotal.Ext[it.ExtKeySDINature].String(), + Natura: exemptExtensionCode(rateTotal.Ext), ImponibileImporto: formatAmount(&rateTotal.Base), Imposta: formatAmount(&rateTotal.Amount), RiferimentoNormativo: findRiferimentoNormativo(rateTotal), @@ -121,11 +131,11 @@ func extractLinePriceAdjustments(line *bill.Line) []*scontoMaggiorazione { } func findRiferimentoNormativo(rateTotal *tax.RateTotal) string { - def := regime.ExtensionDef(it.ExtKeySDINature) + def := tax.ExtensionForKey(sdi.ExtKeyExempt) - nature := rateTotal.Ext[it.ExtKeySDINature].Code() - for _, c := range def.Codes { - if c.Code == nature { + nature := exemptExtensionCode(rateTotal.Ext) + for _, c := range def.Values { + if c.Value == nature { return c.Name[i18n.IT] } } diff --git a/parties.go b/parties.go index 7126b74..d810a8d 100644 --- a/parties.go +++ b/parties.go @@ -1,6 +1,7 @@ package fatturapa import ( + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/cbc" "github.com/invopop/gobl/l10n" "github.com/invopop/gobl/org" @@ -103,7 +104,7 @@ func newSupplier(s *org.Party) *Supplier { Contact: newContact(s), } - if v, ok := s.Ext[it.ExtKeySDIFiscalRegime]; ok { + if v, ok := s.Ext[sdi.ExtKeyFiscalRegime]; ok { ns.Identity.FiscalRegime = v.String() } else { ns.Identity.FiscalRegime = "RF01" @@ -175,14 +176,14 @@ func customerTaxID(id *tax.Identity) *TaxID { code := id.Code.String() if code == "" { - if id.Country == l10n.IT { + if id.Country.Code() == l10n.IT { return nil } // Assume private individual code = nonITCitizenTaxCodeDefault } else { // Must be a company with a local tax ID - if !isEUCountry(id.Country) { + if !isEUCountry(id.Country.Code()) { code = nonEUBusinessTaxCodeDefault } } diff --git a/parties_test.go b/parties_test.go index dd80143..e46b156 100644 --- a/parties_test.go +++ b/parties_test.go @@ -96,7 +96,7 @@ func TestPartiesCustomer(t *testing.T) { env := test.LoadTestFile("invoice-simple.json") test.ModifyInvoice(env, func(inv *bill.Invoice) { inv.Customer.TaxID.Code = "81237984062783472" - inv.Customer.TaxID.Country = l10n.AT + inv.Customer.TaxID.Country = l10n.AT.Tax() }) doc, err := test.ConvertFromGOBL(env) @@ -112,7 +112,7 @@ func TestPartiesCustomer(t *testing.T) { env := test.LoadTestFile("invoice-simple.json") test.ModifyInvoice(env, func(inv *bill.Invoice) { inv.Customer.TaxID.Code = "" - inv.Customer.TaxID.Country = l10n.SE + inv.Customer.TaxID.Country = l10n.SE.Tax() }) doc, err := test.ConvertFromGOBL(env) @@ -128,7 +128,7 @@ func TestPartiesCustomer(t *testing.T) { env := test.LoadTestFile("invoice-simple.json") test.ModifyInvoice(env, func(inv *bill.Invoice) { inv.Customer.TaxID.Code = "09823876432" - inv.Customer.TaxID.Country = l10n.GB + inv.Customer.TaxID.Country = l10n.GB.Tax() }) doc, err := test.ConvertFromGOBL(env) @@ -144,7 +144,7 @@ func TestPartiesCustomer(t *testing.T) { env := test.LoadTestFile("invoice-simple.json") test.ModifyInvoice(env, func(inv *bill.Invoice) { inv.Customer.TaxID.Code = "" - inv.Customer.TaxID.Country = l10n.JP + inv.Customer.TaxID.Country = l10n.JP.Tax() }) doc, err := test.ConvertFromGOBL(env) diff --git a/payments.go b/payments.go index 9d4fedf..fd7d831 100644 --- a/payments.go +++ b/payments.go @@ -3,10 +3,9 @@ package fatturapa import ( "fmt" + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/bill" - "github.com/invopop/gobl/cbc" "github.com/invopop/gobl/pay" - "github.com/invopop/gobl/regimes/it" ) // datiPagamento contains all data related to the payment of the document. @@ -17,44 +16,63 @@ type datiPagamento struct { // dettaglioPagamento contains data related to a single payment. type dettaglioPagamento struct { - ModalitaPagamento string - DataScadenzaPagamento string `xml:",omitempty"` - ImportoPagamento string + ModalitaPagamento string + Date string `xml:"DataRiferimentoTerminiPagamento,omitempty"` + DueDate string `xml:"DataScadenzaPagamento,omitempty"` + ImportoPagamento string } func newDatiPagamento(inv *bill.Invoice) (*datiPagamento, error) { - if inv.Payment == nil || inv.Payment.Instructions == nil { + if inv.Payment == nil { return nil, nil } - dp, err := newDettalgioPagamento(inv) + dp, err := preparePaymentDetails(inv) if err != nil { return nil, err } return &datiPagamento{ - CondizioniPagamento: determinePaymentConditions(inv.Payment), + CondizioniPagamento: determinePaymentConditions(inv), DettaglioPagamento: dp, }, nil } -func newDettalgioPagamento(inv *bill.Invoice) ([]*dettaglioPagamento, error) { +func preparePaymentDetails(inv *bill.Invoice) ([]*dettaglioPagamento, error) { var dp []*dettaglioPagamento payment := inv.Payment - codeModalitaPagamento, err := findCodeModalitaPagamento(payment.Instructions.Key) - if err != nil { - return nil, err + if len(payment.Advances) == 0 && payment.Instructions == nil { + return nil, fmt.Errorf("missing payment advances or instructions") + } + + // First deal with payment advances + for _, advance := range payment.Advances { + row := &dettaglioPagamento{ + ModalitaPagamento: advance.Ext[sdi.ExtKeyPaymentMeans].String(), + ImportoPagamento: formatAmount(&advance.Amount), + } + if advance.Date != nil { + row.Date = advance.Date.String() + } + dp = append(dp, row) } + if payment.Instructions == nil { + // No instructions, ignore anything else + return dp, nil + } + + codeModalitaPagamento := payment.Instructions.Ext[sdi.ExtKeyPaymentMeans].String() + // First check if there are multiple due dates, and if so, create a // DettaglioPagamento for each one. if terms := payment.Terms; terms != nil { for _, dueDate := range payment.Terms.DueDates { dp = append(dp, &dettaglioPagamento{ - ModalitaPagamento: codeModalitaPagamento, - DataScadenzaPagamento: dueDate.Date.String(), // ISO 8601 YYYY-MM-DD format - ImportoPagamento: formatAmount(&dueDate.Amount), + ModalitaPagamento: codeModalitaPagamento, + DueDate: dueDate.Date.String(), // ISO 8601 YYYY-MM-DD format + ImportoPagamento: formatAmount(&dueDate.Amount), }) } } @@ -71,38 +89,13 @@ func newDettalgioPagamento(inv *bill.Invoice) ([]*dettaglioPagamento, error) { return dp, nil } -func findCodeModalitaPagamento(key cbc.Key) (string, error) { - keyDef := findPaymentKeyDefinition(key) - - if keyDef == nil { - return "", fmt.Errorf("ModalitaPagamento Code not found for payment method key '%s'", key) - } - - code := keyDef.Map[it.KeyFatturaPAModalitaPagamento] - if code == "" { - return "", fmt.Errorf("ModalitaPagamento Code not found for payment method key '%s'", key) - } - - return code.String(), nil -} - -func findPaymentKeyDefinition(key cbc.Key) *cbc.KeyDefinition { - for _, keyDef := range regime.PaymentMeansKeys { - if key == keyDef.Key { - return keyDef - } - } - return nil -} - -func determinePaymentConditions(payment *bill.Payment) string { +func determinePaymentConditions(inv *bill.Invoice) string { + p := inv.Payment switch { - case payment.Terms == nil: - return condizioniPagamentoFull - case len(payment.Terms.DueDates) > 1: - return condizioniPagamentoInstallments - case payment.Terms.Key == pay.TermKeyAdvanced: + case inv.Totals.Paid() || (p.Terms != nil && p.Terms.Key == pay.TermKeyAdvanced): return condizioniPagamentoAdvance + case len(p.Advances) > 0 || (p.Terms != nil && len(p.Terms.DueDates) > 1): + return condizioniPagamentoInstallments default: return condizioniPagamentoFull } diff --git a/payments_test.go b/payments_test.go index 30d11f0..1a143be 100644 --- a/payments_test.go +++ b/payments_test.go @@ -24,8 +24,8 @@ func TestPaymentsSimple(t *testing.T) { }) } -func TestPaymentsMultipleDueDates(t *testing.T) { - t.Run("should contain the customer party info", func(t *testing.T) { +func TestPayments(t *testing.T) { + t.Run("multiple due dates", func(t *testing.T) { env := test.LoadTestFile("invoice-irpef.json") doc, err := test.ConvertFromGOBL(env) require.NoError(t, err) @@ -36,10 +36,38 @@ func TestPaymentsMultipleDueDates(t *testing.T) { assert.Equal(t, "TP01", dp.CondizioniPagamento) assert.Len(t, dp.DettaglioPagamento, 2) assert.Equal(t, "MP05", dp.DettaglioPagamento[0].ModalitaPagamento) - assert.Equal(t, "2023-03-02", dp.DettaglioPagamento[0].DataScadenzaPagamento) + assert.Equal(t, "2023-03-02", dp.DettaglioPagamento[0].DueDate) assert.Equal(t, "500.00", dp.DettaglioPagamento[0].ImportoPagamento) assert.Equal(t, "MP05", dp.DettaglioPagamento[1].ModalitaPagamento) - assert.Equal(t, "2023-04-02", dp.DettaglioPagamento[1].DataScadenzaPagamento) + assert.Equal(t, "2023-04-02", dp.DettaglioPagamento[1].DueDate) assert.Equal(t, "544.40", dp.DettaglioPagamento[1].ImportoPagamento) }) + + t.Run("advance payment", func(t *testing.T) { + env := test.LoadTestFile("invoice-hotel-private.json") + doc, err := test.ConvertFromGOBL(env) + require.NoError(t, err) + + dp := doc.FatturaElettronicaBody[0].DatiPagamento + + require.NotNil(t, dp) + assert.Equal(t, "TP01", dp.CondizioniPagamento) + assert.Len(t, dp.DettaglioPagamento, 1) + assert.Equal(t, "MP08", dp.DettaglioPagamento[0].ModalitaPagamento) + assert.Equal(t, "29.00", dp.DettaglioPagamento[0].ImportoPagamento) + }) + + t.Run("prepaid", func(t *testing.T) { + env := test.LoadTestFile("invoice-hotel.json") + doc, err := test.ConvertFromGOBL(env) + require.NoError(t, err) + + dp := doc.FatturaElettronicaBody[0].DatiPagamento + + require.NotNil(t, dp) + assert.Equal(t, "TP03", dp.CondizioniPagamento) + assert.Len(t, dp.DettaglioPagamento, 1) + assert.Equal(t, "MP08", dp.DettaglioPagamento[0].ModalitaPagamento) + assert.Equal(t, "241.00", dp.DettaglioPagamento[0].ImportoPagamento) + }) } diff --git a/regime.go b/regime.go index d594841..4b10d4a 100644 --- a/regime.go +++ b/regime.go @@ -1,8 +1,3 @@ package fatturapa -import ( - "github.com/invopop/gobl/l10n" - "github.com/invopop/gobl/tax" -) - -var regime = tax.RegimeFor(l10n.IT) +// var regime = tax.RegimeFor(l10n.IT) diff --git a/retained_taxes.go b/retained_taxes.go index bb0b83b..645fca8 100644 --- a/retained_taxes.go +++ b/retained_taxes.go @@ -3,6 +3,7 @@ package fatturapa import ( "fmt" + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/bill" "github.com/invopop/gobl/cbc" "github.com/invopop/gobl/regimes/it" @@ -58,18 +59,33 @@ func newDatiRitenuta(cat cbc.Code, rateTotal *tax.RateTotal) (*datiRitenuta, err TipoRitenuta: codeTR, ImportoRitenuta: amount, AliquotaRitenuta: rate, - CausalePagamento: rateTotal.Ext[it.ExtKeySDIRetainedTax].String(), + CausalePagamento: retainedExtensionCode(rateTotal.Ext), }, nil } -func findCodeTipoRitenuta(cat cbc.Code) (string, error) { - taxCategory := regime.Category(cat) - - code := taxCategory.Map[it.KeyFatturaPATipoRitenuta] +func retainedExtensionCode(ext tax.Extensions) string { + if ext.Has(sdi.ExtKeyRetained) { + return ext[sdi.ExtKeyRetained].String() + } + if ext.Has("it-sdi-retained-tax") { // old key + return ext["it-sdi-retained-tax"].String() + } + return "" +} - if code == "" { +func findCodeTipoRitenuta(cat cbc.Code) (string, error) { + switch cat { + case it.TaxCategoryIRPEF: + return "RT01", nil + case it.TaxCategoryIRES: + return "RT02", nil + case it.TaxCategoryINPS: + return "RT03", nil + case it.TaxCategoryENASARCO: + return "RT04", nil + case it.TaxCategoryENPAM: + return "RT05", nil + default: return "", fmt.Errorf("could not find TipoRitenuta code for tax category %s", cat) } - - return code.String(), nil } diff --git a/test/data/invoice-hotel-private.json b/test/data/invoice-hotel-private.json index 085a1ca..2ebea6f 100644 --- a/test/data/invoice-hotel-private.json +++ b/test/data/invoice-hotel-private.json @@ -4,11 +4,15 @@ "uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6", "dig": { "alg": "sha256", - "val": "d0bb18b72b2ad7b226a82829dbeceee17e139d8b8cb8e5844644e4b7071bd7c6" + "val": "d77d55ff1a97da6aca862f027472d5804bb8549a6fb0226106238afc24c5124a" } }, "doc": { "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "IT", + "$addons": [ + "it-sdi-v1" + ], "uuid": "018f76a8-958f-7000-ac84-68b205937de3", "type": "standard", "series": "SAMPLE", @@ -16,7 +20,11 @@ "issue_date": "2023-05-21", "currency": "EUR", "tax": { - "prices_include": "VAT" + "prices_include": "VAT", + "ext": { + "it-sdi-document-type": "TD01", + "it-sdi-format": "FPR12" + } }, "supplier": { "name": "Hotel California", @@ -39,6 +47,9 @@ "currency": "EUR", "office": "RM", "entry": "123456" + }, + "ext": { + "it-sdi-fiscal-regime": "RF01" } }, "customer": { @@ -78,7 +89,7 @@ "cat": "VAT", "rate": "exempt", "ext": { - "it-sdi-nature": "N1" + "it-sdi-exempt": "N1" } } ], @@ -125,7 +136,10 @@ "date": "2023-05-01", "key": "card", "description": "deposit", - "amount": "29.00" + "amount": "29.00", + "ext": { + "it-sdi-payment-means": "MP08" + } } ] }, @@ -141,7 +155,7 @@ { "key": "exempt", "ext": { - "it-sdi-nature": "N1" + "it-sdi-exempt": "N1" }, "base": "1.00", "amount": "0.00" diff --git a/test/data/invoice-hotel.json b/test/data/invoice-hotel.json index 040a0eb..7660720 100644 --- a/test/data/invoice-hotel.json +++ b/test/data/invoice-hotel.json @@ -4,11 +4,15 @@ "uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6", "dig": { "alg": "sha256", - "val": "4b6ec1bb24bdd707520a89e632279966d887f0a3339dc737c30f69f7664c5345" + "val": "c213970a17cc70d4babe036c177d30e9045383652cf6caf11a7edf475b39e014" } }, "doc": { "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "IT", + "$addons": [ + "it-sdi-v1" + ], "uuid": "0190caea-c344-7afa-a530-252b67108175", "type": "standard", "series": "SAMPLE", @@ -16,7 +20,11 @@ "issue_date": "2023-05-21", "currency": "EUR", "tax": { - "prices_include": "VAT" + "prices_include": "VAT", + "ext": { + "it-sdi-document-type": "TD01", + "it-sdi-format": "FPR12" + } }, "supplier": { "name": "Hotel California", @@ -38,6 +46,9 @@ "currency": "EUR", "office": "RM", "entry": "123456" + }, + "ext": { + "it-sdi-fiscal-regime": "RF01" } }, "customer": { @@ -77,7 +88,7 @@ "cat": "VAT", "rate": "exempt", "ext": { - "it-sdi-nature": "N1" + "it-sdi-exempt": "N1" } } ], @@ -113,7 +124,11 @@ "date": "2023-05-01", "key": "card", "description": "deposit", - "amount": "29.00" + "percent": "100%", + "amount": "241.00", + "ext": { + "it-sdi-payment-means": "MP08" + } } ] }, @@ -129,7 +144,7 @@ { "key": "exempt", "ext": { - "it-sdi-nature": "N1" + "it-sdi-exempt": "N1" }, "base": "1.00", "amount": "0.00" @@ -149,8 +164,8 @@ "tax": "21.82", "total_with_tax": "241.00", "payable": "241.00", - "advance": "29.00", - "due": "212.00" + "advance": "241.00", + "due": "0.00" } } } \ No newline at end of file diff --git a/test/data/invoice-irpef.json b/test/data/invoice-irpef.json index 1aa8de8..b275965 100644 --- a/test/data/invoice-irpef.json +++ b/test/data/invoice-irpef.json @@ -4,11 +4,18 @@ "uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6", "dig": { "alg": "sha256", - "val": "5df55bfe1a0d605d9be685ea1c2c0d020d9cdf6626f2c0717f2fe8ae30b94035" + "val": "1a7ebf9bcec0525294d085a246c528304ed1317e52652e1e17f37fb4f12a7271" } }, "doc": { "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "IT", + "$addons": [ + "it-sdi-v1" + ], + "$tags": [ + "freelance" + ], "uuid": "0190caea-c352-7310-90fe-cbf74a3cd084", "type": "standard", "series": "SAMPLE", @@ -16,9 +23,10 @@ "issue_date": "2023-03-02", "currency": "EUR", "tax": { - "tags": [ - "freelance" - ] + "ext": { + "it-sdi-document-type": "TD06", + "it-sdi-format": "FPR12" + } }, "supplier": { "name": "Rossi Digital Services", @@ -48,7 +56,10 @@ { "addr": "billing@example.com" } - ] + ], + "ext": { + "it-sdi-fiscal-regime": "RF01" + } }, "customer": { "name": "MARIO LEONI", @@ -119,7 +130,7 @@ "cat": "IRPEF", "percent": "20.0%", "ext": { - "it-sdi-retained-tax": "A" + "it-sdi-retained": "A" } } ], @@ -139,14 +150,14 @@ "cat": "VAT", "rate": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" } }, { "cat": "IRPEF", "percent": "50.0%", "ext": { - "it-sdi-retained-tax": "I" + "it-sdi-retained": "I" } } ], @@ -198,7 +209,10 @@ "bic": "BCITITMM", "name": "BANCA POPOLARE DI MILANO" } - ] + ], + "ext": { + "it-sdi-payment-means": "MP05" + } } }, "totals": { @@ -220,7 +234,7 @@ { "key": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" }, "base": "100.00", "amount": "0.00" @@ -234,7 +248,7 @@ "rates": [ { "ext": { - "it-sdi-retained-tax": "A" + "it-sdi-retained": "A" }, "base": "1620.00", "percent": "20.0%", @@ -242,7 +256,7 @@ }, { "ext": { - "it-sdi-retained-tax": "I" + "it-sdi-retained": "I" }, "base": "100.00", "percent": "50.0%", diff --git a/test/data/invoice-simple-with-pec.json b/test/data/invoice-simple-with-pec.json index caf1e2b..45159fa 100644 --- a/test/data/invoice-simple-with-pec.json +++ b/test/data/invoice-simple-with-pec.json @@ -4,11 +4,18 @@ "uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6", "dig": { "alg": "sha256", - "val": "af8a70f8e1d7a666ffd2abf461f223bfa5805af14657b00c39c1615d17fc315b" + "val": "3a010567cc0f19963f2d6eb35418a11aa2a53dd3abc973bd4136d924e1a83802" } }, "doc": { "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "IT", + "$addons": [ + "it-sdi-v1" + ], + "$tags": [ + "freelance" + ], "uuid": "0190caea-c35f-72c1-92a0-728defa74ce2", "type": "standard", "series": "SAMPLE", @@ -16,9 +23,10 @@ "issue_date": "2023-03-02", "currency": "EUR", "tax": { - "tags": [ - "freelance" - ] + "ext": { + "it-sdi-document-type": "TD06", + "it-sdi-format": "FPR12" + } }, "supplier": { "name": "MªF. Services", @@ -141,7 +149,7 @@ "cat": "VAT", "rate": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" } } ], @@ -168,7 +176,10 @@ ], "payment": { "instructions": { - "key": "card" + "key": "card", + "ext": { + "it-sdi-payment-means": "MP08" + } } }, "totals": { @@ -190,7 +201,7 @@ { "key": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" }, "base": "100.00", "amount": "0.00" diff --git a/test/data/invoice-simple.json b/test/data/invoice-simple.json index 84ff9b8..fa77531 100644 --- a/test/data/invoice-simple.json +++ b/test/data/invoice-simple.json @@ -4,11 +4,18 @@ "uuid": "679a2f25-7483-11ec-9722-7ea2cb436ff6", "dig": { "alg": "sha256", - "val": "c039dc11fc9e45449c998d603c43f8b3dc3bc87c9cf80d269d7730e7c939a7c3" + "val": "308a3db3311dbfee897317f2d7ce0248613a1863c1a8ef3c48a318126cea37a3" } }, "doc": { "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "IT", + "$addons": [ + "it-sdi-v1" + ], + "$tags": [ + "freelance" + ], "uuid": "0190c0ec-8109-756b-a4f0-88c4b542ab6e", "type": "standard", "series": "SAMPLE", @@ -16,9 +23,10 @@ "issue_date": "2023-03-02", "currency": "EUR", "tax": { - "tags": [ - "freelance" - ] + "ext": { + "it-sdi-document-type": "TD06", + "it-sdi-format": "FPR12" + } }, "supplier": { "name": "MªF. Services", @@ -141,7 +149,7 @@ "cat": "VAT", "rate": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" } } ], @@ -168,7 +176,10 @@ ], "payment": { "instructions": { - "key": "card" + "key": "card", + "ext": { + "it-sdi-payment-means": "MP08" + } } }, "totals": { @@ -190,7 +201,7 @@ { "key": "exempt", "ext": { - "it-sdi-nature": "N2.2" + "it-sdi-exempt": "N2.2" }, "base": "100.00", "amount": "0.00" diff --git a/test/data/out/invoice-hotel-private.xml b/test/data/out/invoice-hotel-private.xml index cfb2f18..287d32a 100644 --- a/test/data/out/invoice-hotel-private.xml +++ b/test/data/out/invoice-hotel-private.xml @@ -104,6 +104,14 @@ 79.55 + + TP01 + + MP08 + 2023-05-01 + 29.00 + + @@ -114,7 +122,7 @@ - GoD0VAc+efNSNyTCsAt50+3vdJtBnIbZRVg6geyiZA120uO/sSVKVX/V+Tc3kdmiIQyS19kRZr6J+t5QS3Ting== + vuZ5E6coxpN0RjbO74LJ+e/Ool3hlLWugeNhPrepcyp9zXc6HW7zLGAvDB8ribuy4Kw+gzQ39RGP3dDYqK8EvA== @@ -125,7 +133,7 @@ 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 diff --git a/test/data/out/invoice-hotel.xml b/test/data/out/invoice-hotel.xml index 68b47e2..fb15e86 100644 --- a/test/data/out/invoice-hotel.xml +++ b/test/data/out/invoice-hotel.xml @@ -100,6 +100,14 @@ 21.82 + + TP03 + + MP08 + 2023-05-01 + 241.00 + + @@ -110,7 +118,7 @@ - 4KAycPCYtM1f6vffnVi5gWc6nFXhyM2gMCRF61WzyF8/jWna05ffdB89Fz1bMn8ijwrJrJDA7iM3sFWBmMgY6g== + o6UBSvL05Xip2GqWwwezI21zZRhTCC81+s0/JjeFEZ8E+8kq9wm/LhibiHvdpOdl3r8ttW+0y7QGnuxdCdY5Jg== @@ -121,7 +129,7 @@ 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 diff --git a/transmission.go b/transmission.go index ddf7742..f04981e 100644 --- a/transmission.go +++ b/transmission.go @@ -2,10 +2,10 @@ package fatturapa import ( "github.com/invopop/gobl" + "github.com/invopop/gobl/addons/it/sdi" "github.com/invopop/gobl/bill" "github.com/invopop/gobl/l10n" "github.com/invopop/gobl/org" - "github.com/invopop/gobl/regimes/it" ) const ( @@ -50,8 +50,8 @@ func (c *Converter) newDatiTrasmissione(inv *bill.Invoice, env *gobl.Envelope) * } func formatoTransmissione(inv *bill.Invoice) string { - if inv.Tax != nil && inv.Tax.Ext.Has(it.ExtKeySDIFormat) { - return inv.Tax.Ext[it.ExtKeySDIFormat].String() + if inv.Tax != nil && inv.Tax.Ext.Has(sdi.ExtKeyFormat) { + return inv.Tax.Ext[sdi.ExtKeyFormat].String() } // Default is always FPR12 for regular non-government invoices @@ -60,11 +60,11 @@ func formatoTransmissione(inv *bill.Invoice) string { func codiceDestinatario(cus *org.Party) string { if cus != nil { - if cus.TaxID != nil && cus.TaxID.Country != l10n.IT { + if cus.TaxID != nil && cus.TaxID.Country.Code() != l10n.IT { return defaultCodiceDestinatarioForeignBusiness } for _, inbox := range cus.Inboxes { - if inbox.Key == it.KeyInboxSDICode { + if inbox.Key == sdi.KeyInboxCode { return inbox.Code } } @@ -78,7 +78,7 @@ func codiceDestinatario(cus *org.Party) string { func pecDestinatario(cus *org.Party) string { if cus != nil { for _, inbox := range cus.Inboxes { - if inbox.Key == it.KeyInboxSDIPEC { + if inbox.Key == sdi.KeyInboxPEC { return inbox.Code } }