diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index 14aa2ae..63a17b6 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -13,15 +13,15 @@ jobs:
steps:
- name: Check out code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Go
- uses: actions/setup-go@v4
+ uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
id: go
- name: Lint
- uses: golangci/golangci-lint-action@v2
+ uses: golangci/golangci-lint-action@v6
with:
version: v1.58
diff --git a/README.md b/README.md
index 9e6a283..428640c 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Unlike other tax regimes, Italy requires simplified invoices to include the cust
## Sources
-You can find copies of the Italian FatturaPA schema in the [schemas folder](./schema).
+You can find copies of the Italian FatturaPA schema in the [schemas folder](./schemas).
Key websites:
@@ -46,11 +46,6 @@ The FatturaPA XML schema is quite large and complex. This library is not complet
Some of the optional elements currently not supported include:
- `Allegati` (attachments)
-- `DatiOrdineAcquisto` (data related to purchase orders)
-- `DatiContratto` (data related to contracts)
-- `DatiConvenzione` (data related to conventions)
-- `DatiRicezione` (data related to receipts)
-- `DatiFattureCollegate` (data related to linked invoices)
- `DatiBollo` (data related to duty stamps)
## Usage
diff --git a/body.go b/body.go
index 7a6e4eb..3823781 100644
--- a/body.go
+++ b/body.go
@@ -7,6 +7,7 @@ import (
"github.com/invopop/gobl/addons/it/sdi"
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cbc"
+ "github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/it"
)
@@ -26,15 +27,31 @@ const stampDutyCode = "SI"
// fatturaElettronicaBody contains all invoice data apart from the parties
// involved, which are contained in FatturaElettronicaHeader.
type fatturaElettronicaBody struct {
- DatiGenerali *datiGenerali
+ DatiGenerali *GeneralData `xml:"DatiGenerali,omitempty"`
DatiBeniServizi *datiBeniServizi
DatiPagamento *datiPagamento `xml:",omitempty"`
}
-// datiGenerali contains general data about the invoice such as retained taxes,
+// GeneralData contains general data about the invoice such as retained taxes,
// invoice number, invoice date, document type, etc.
-type datiGenerali struct {
- DatiGeneraliDocumento *datiGeneraliDocumento
+type GeneralData struct {
+ Document *datiGeneraliDocumento `xml:"DatiGeneraliDocumento"`
+ Purchases []*DocumentRef `xml:"DatiOrdineAcquisto,omitempty"`
+ Contracts []*DocumentRef `xml:"DatiContratto,omitempty"`
+ Tender []*DocumentRef `xml:"DatiConvenzione,omitempty"`
+ Receiving []*DocumentRef `xml:"DatiRicezione,omitempty"`
+ Preceding []*DocumentRef `xml:"DatiFattureCollegate,omitempty"`
+}
+
+// DocumentRef contains data about a previous document.
+type DocumentRef struct {
+ Lines []int `xml:"RiferimentoNumeroLinea"` // detail row of the invoice referred to (if the reference is to the entire invoice, this is not filled in)
+ Code string `xml:"IdDocumento"` // document number
+ IssueDate string `xml:"Data,omitempty"` // document date (expressed according to the ISO 8601:2004 format)
+ LineCode string `xml:"NumItem,omitempty"` // identification of the single item on the document (e.g. in the case of a purchase order, this is the number of the row of the purchase order, or, in the case of a contract, it is the number of the row of the contract, etc. )
+ OrderCode string `xml:"CodiceCommessaConvenzione,omitempty"` // order or agreement code
+ CUPCode string `xml:"CodiceCUP,omitempty"` // code managed by the CIPE (Interministerial Committee for Economic Planning) which characterises every public investment project (Individual Project Code).
+ CIGCode string `xml:"CodiceCIG,omitempty"` // Tender procedure identification code
}
type datiGeneraliDocumento struct {
@@ -71,7 +88,7 @@ func newFatturaElettronicaBody(inv *bill.Invoice) (*fatturaElettronicaBody, erro
return nil, err
}
- dg, err := newDatiGenerali(inv)
+ dg, err := newGeneralData(inv)
if err != nil {
return nil, err
}
@@ -83,7 +100,57 @@ func newFatturaElettronicaBody(inv *bill.Invoice) (*fatturaElettronicaBody, erro
}, nil
}
-func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) {
+func newGeneralData(inv *bill.Invoice) (*GeneralData, error) {
+ gd := new(GeneralData)
+ var err error
+ if gd.Document, err = newGeneralDataDocument(inv); err != nil {
+ return nil, err
+ }
+ gd.Preceding = newDocumentRefs(inv.Preceding)
+ if o := inv.Ordering; o != nil {
+ gd.Purchases = newDocumentRefs(o.Purchases)
+ gd.Contracts = newDocumentRefs(o.Contracts)
+ gd.Tender = newDocumentRefs(o.Tender)
+ gd.Receiving = newDocumentRefs(o.Receiving)
+ }
+ return gd, nil
+}
+
+func newDocumentRefs(refs []*org.DocumentRef) []*DocumentRef {
+ out := make([]*DocumentRef, len(refs))
+ for i, ref := range refs {
+ out[i] = newDocumentRef(ref)
+ }
+ return out
+}
+
+func newDocumentRef(ref *org.DocumentRef) *DocumentRef {
+ dr := &DocumentRef{
+ Lines: ref.Lines,
+ Code: ref.Series.Join(ref.Code).String(),
+ }
+ if ref.IssueDate != nil {
+ dr.IssueDate = ref.IssueDate.String()
+ }
+ for _, id := range ref.Identities {
+ switch id.Key {
+ case org.IdentityKeyOrder:
+ dr.OrderCode = string(id.Code)
+ case org.IdentityKeyItem:
+ dr.LineCode = string(id.Code)
+ }
+ switch id.Type {
+ case sdi.IdentityTypeCIG:
+ dr.CIGCode = string(id.Code)
+ case sdi.IdentityTypeCUP:
+ dr.CUPCode = string(id.Code)
+ }
+ }
+
+ return dr
+}
+
+func newGeneralDataDocument(inv *bill.Invoice) (*datiGeneraliDocumento, error) {
dr, err := extractRetainedTaxes(inv)
if err != nil {
return nil, err
@@ -104,19 +171,19 @@ func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) {
code = cbc.Code(fmt.Sprintf("%s-%s", inv.Series, inv.Code))
}
- return &datiGenerali{
- DatiGeneraliDocumento: &datiGeneraliDocumento{
- TipoDocumento: codeTipoDocumento,
- Divisa: string(inv.Currency),
- Data: inv.IssueDate.String(),
- Numero: code.String(),
- DatiRitenuta: dr,
- DatiBollo: newDatiBollo(inv.Charges),
- ImportoTotaleDocumento: formatAmount(&inv.Totals.Payable),
- ScontoMaggiorazione: extractPriceAdjustments(inv),
- Causale: extractInvoiceReasons(inv),
- },
- }, nil
+ doc := &datiGeneraliDocumento{
+ TipoDocumento: codeTipoDocumento,
+ Divisa: string(inv.Currency),
+ Data: inv.IssueDate.String(),
+ Numero: code.String(),
+ DatiRitenuta: dr,
+ DatiBollo: newDatiBollo(inv.Charges),
+ ImportoTotaleDocumento: formatAmount(&inv.Totals.Payable),
+ ScontoMaggiorazione: extractPriceAdjustments(inv),
+ Causale: extractInvoiceReasons(inv),
+ }
+
+ return doc, nil
}
func findCodeTipoDocumento(inv *bill.Invoice) (string, error) {
diff --git a/cmd/gobl.fatturapa/convert.go b/cmd/gobl.fatturapa/convert.go
index 8f05d8f..643c217 100644
--- a/cmd/gobl.fatturapa/convert.go
+++ b/cmd/gobl.fatturapa/convert.go
@@ -2,8 +2,11 @@
package main
import (
+ "bytes"
+ "encoding/json"
"fmt"
+ "github.com/invopop/gobl"
fatturapa "github.com/invopop/gobl.fatturapa"
"github.com/invopop/gobl/l10n"
"github.com/invopop/xmldsig"
@@ -55,8 +58,12 @@ func (c *convertOpts) runE(cmd *cobra.Command, args []string) error {
return err
}
- env, err := fatturapa.UnmarshalGOBL(input)
- if err != nil {
+ buf := new(bytes.Buffer)
+ if _, err := buf.ReadFrom(input); err != nil {
+ panic(err)
+ }
+ env := new(gobl.Envelope)
+ if err := json.Unmarshal(buf.Bytes(), env); err != nil {
return err
}
diff --git a/converter.go b/converter.go
index 3aac9da..fcf2ffc 100644
--- a/converter.go
+++ b/converter.go
@@ -1,12 +1,8 @@
package fatturapa
import (
- "bytes"
- "encoding/json"
- "io"
"time"
- "github.com/invopop/gobl"
"github.com/invopop/xmldsig"
)
@@ -72,18 +68,3 @@ func NewConverter(opts ...Option) *Converter {
return c
}
-
-// UnmarshalGOBL converts the given JSON document to a GOBL Envelope
-func UnmarshalGOBL(reader io.Reader) (*gobl.Envelope, error) {
- buf := new(bytes.Buffer)
- if _, err := buf.ReadFrom(reader); err != nil {
- return nil, err
- }
-
- env := new(gobl.Envelope)
- if err := json.Unmarshal(buf.Bytes(), env); err != nil {
- return nil, err
- }
-
- return env, nil
-}
diff --git a/go.mod b/go.mod
index fd5bf8d..dfa503f 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.22
toolchain go1.22.5
require (
- github.com/invopop/gobl v0.200.0-rc3
+ github.com/invopop/gobl v0.202.0
github.com/invopop/xmldsig v0.8.0
github.com/lestrrat-go/libxml2 v0.0.0-20240521004304-a75c203ac627
github.com/spf13/cobra v1.8.1
diff --git a/go.sum b/go.sum
index cf40104..1b9398e 100644
--- a/go.sum
+++ b/go.sum
@@ -22,8 +22,8 @@ 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.200.0-rc3 h1:Y/sQMQHufdlNx5Jlx78bnrValco/JLIqA9WbJjbLi5M=
-github.com/invopop/gobl v0.200.0-rc3/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU=
+github.com/invopop/gobl v0.202.0 h1:iUKk7FCKHbEKzuK7qAIxRkZAuh/8g09F9+Ufvs7aWbM=
+github.com/invopop/gobl v0.202.0/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.7.0 h1:NBPLqvYGmLZLQuk5jh0PbaBBetJW7f2VEk/BTWJkGBU=
diff --git a/retained_taxes_test.go b/retained_taxes_test.go
index 651b7fd..fa8908a 100644
--- a/retained_taxes_test.go
+++ b/retained_taxes_test.go
@@ -9,25 +9,25 @@ import (
)
func TestDatiRitenuta(t *testing.T) {
- t.Run("When retained taxes are NOT present", func(t *testing.T) {
+ t.Run("when retained taxes are NOT present", func(t *testing.T) {
t.Run("should be empty", func(t *testing.T) {
env := test.LoadTestFile("invoice-simple.json")
doc, err := test.ConvertFromGOBL(env)
require.NoError(t, err)
- dr := doc.FatturaElettronicaBody[0].DatiGenerali.DatiGeneraliDocumento.DatiRitenuta
+ dr := doc.FatturaElettronicaBody[0].DatiGenerali.Document.DatiRitenuta
assert.Empty(t, dr)
})
})
- t.Run("When retained taxes are present", func(t *testing.T) {
+ t.Run("when retained taxes are present", func(t *testing.T) {
t.Run("should contain the correct retainted taxes", func(t *testing.T) {
env := test.LoadTestFile("invoice-irpef.json")
doc, err := test.ConvertFromGOBL(env)
require.NoError(t, err)
- dr := doc.FatturaElettronicaBody[0].DatiGenerali.DatiGeneraliDocumento.DatiRitenuta
+ dr := doc.FatturaElettronicaBody[0].DatiGenerali.Document.DatiRitenuta
require.Len(t, dr, 2)
diff --git a/schema/fatturapav1_2_2.xsd b/schema/fatturapav1_2_2.xsd
deleted file mode 100644
index 237eb4b..0000000
--- a/schema/fatturapav1_2_2.xsd
+++ /dev/null
@@ -1,1446 +0,0 @@
-
-
-
-
-
- XML schema fatture destinate a PA e privati in forma ordinaria 1.2.2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati di trasmissione della Fattura Elettronica
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Fattura verso PA
-
-
-
-
- Fattura verso privati
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai Dati Generali della Fattura Elettronica
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SC = Sconto
-
-
-
-
- MG = Maggiorazione
-
-
-
-
-
-
-
-
-
- SI = Documento emesso secondo modalità e termini stabiliti con DM ai sensi dell'art. 73 DPR 633/72
-
-
-
-
-
-
-
-
-
- Cassa nazionale previdenza e assistenza avvocati e procuratori legali
-
-
-
-
- Cassa previdenza dottori commercialisti
-
-
-
-
- Cassa previdenza e assistenza geometri
-
-
-
-
- Cassa nazionale previdenza e assistenza ingegneri e architetti liberi professionisti
-
-
-
-
- Cassa nazionale del notariato
-
-
-
-
- Cassa nazionale previdenza e assistenza ragionieri e periti commerciali
-
-
-
-
- Ente nazionale assistenza agenti e rappresentanti di commercio (ENASARCO)
-
-
-
-
- Ente nazionale previdenza e assistenza consulenti del lavoro (ENPACL)
-
-
-
-
- Ente nazionale previdenza e assistenza medici (ENPAM)
-
-
-
-
- Ente nazionale previdenza e assistenza farmacisti (ENPAF)
-
-
-
-
- Ente nazionale previdenza e assistenza veterinari (ENPAV)
-
-
-
-
- Ente nazionale previdenza e assistenza impiegati dell'agricoltura (ENPAIA)
-
-
-
-
- Fondo previdenza impiegati imprese di spedizione e agenzie marittime
-
-
-
-
- Istituto nazionale previdenza giornalisti italiani (INPGI)
-
-
-
-
- Opera nazionale assistenza orfani sanitari italiani (ONAOSI)
-
-
-
-
- Cassa autonoma assistenza integrativa giornalisti italiani (CASAGIT)
-
-
-
-
- Ente previdenza periti industriali e periti industriali laureati (EPPI)
-
-
-
-
- Ente previdenza e assistenza pluricategoriale (EPAP)
-
-
-
-
- Ente nazionale previdenza e assistenza biologi (ENPAB)
-
-
-
-
- Ente nazionale previdenza e assistenza professione infermieristica (ENPAPI)
-
-
-
-
- Ente nazionale previdenza e assistenza psicologi (ENPAP)
-
-
-
-
- INPS
-
-
-
-
-
-
-
-
-
- Fattura
-
-
-
-
- Acconto / anticipo su fattura
-
-
-
-
- Acconto / anticipo su parcella
-
-
-
-
- Nota di credito
-
-
-
-
- Nota di debito
-
-
-
-
- Parcella
-
-
-
-
- Integrazione fattura reverse charge interno
-
-
-
-
- Integrazione/autofattura per acquisto servizi dall'estero
-
-
-
-
- Integrazione per acquisto di beni intracomunitari
-
-
-
-
- Integrazione/autofattura per acquisto di beni ex art.17 c.2 DPR 633/72
-
-
-
-
- Autofattura per regolarizzazione e integrazione delle fatture (ex art.6 c.8 e 9-bis d.lgs.471/97 o art.46 c.5 D.L. 331/93
-
-
-
-
- Autofattura per splafonamento
-
-
-
-
- Estrazione benida Deposito IVA
-
-
-
-
- Estrazione beni da Deposito IVA con versamento dell'IVA
-
-
-
-
- Fattura differita di cui all'art.21, comma 4, terzo periodo lett. a) DPR 633/72
-
-
-
-
- Fattura differita di cui all'art.21, comma 4, terzo periodo lett. b) DPR 633/72
-
-
-
-
- Cessione di beni ammortizzabili e per passaggi interni (ex art.36 DPR 633/72)
-
-
-
-
- Fattura per autoconsumo o per cessioni gratuite senza rivalsa
-
-
-
-
- Acquisti da San Marino con IVA (fattura cartacea)
-
-
-
-
-
-
-
-
-
- Ritenuta di acconto persone fisiche
-
-
-
-
- Ritenuta di acconto persone giuridiche
-
-
-
-
- Contributo INPS
-
-
-
-
- Contributo ENASARCO
-
-
-
-
- Contributo ENPAM
-
-
-
-
- Altro contributo previdenziale
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cessionario / Committente
-
-
-
-
- Terzo
-
-
-
-
-
-
- Blocco relativo ai dati del Cedente / Prestatore
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Regime ordinario
-
-
-
-
- Regime dei contribuenti minimi (art. 1,c.96-117, L. 244/2007)
-
-
-
-
- Agricoltura e attività connesse e pesca (artt. 34 e 34-bis, D.P.R. 633/1972)
-
-
-
-
- Vendita sali e tabacchi (art. 74, c.1, D.P.R. 633/1972)
-
-
-
-
- Commercio dei fiammiferi (art. 74, c.1, D.P.R. 633/1972)
-
-
-
-
- Editoria (art. 74, c.1, D.P.R. 633/1972)
-
-
-
-
- Gestione di servizi di telefonia pubblica (art. 74, c.1, D.P.R. 633/1972)
-
-
-
-
- Rivendita di documenti di trasporto pubblico e di sosta (art. 74, c.1, D.P.R. 633/1972)
-
-
-
-
- Intrattenimenti, giochi e altre attività di cui alla tariffa allegata al D.P.R. 640/72 (art. 74, c.6, D.P.R. 633/1972)
-
-
-
-
- Agenzie di viaggi e turismo (art. 74-ter, D.P.R. 633/1972)
-
-
-
-
- Agriturismo (art. 5, c.2, L. 413/1991)
-
-
-
-
- Vendite a domicilio (art. 25-bis, c.6, D.P.R. 600/1973)
-
-
-
-
- Rivendita di beni usati, di oggetti d’arte, d’antiquariato o da collezione (art. 36, D.L. 41/1995)
-
-
-
-
- Agenzie di vendite all’asta di oggetti d’arte, antiquariato o da collezione (art. 40-bis, D.L. 41/1995)
-
-
-
-
- IVA per cassa P.A. (art. 6, c.5, D.P.R. 633/1972)
-
-
-
-
- IVA per cassa (art. 32-bis, D.L. 83/2012)
-
-
-
-
- Regime forfettario
-
-
-
-
- Altro
-
-
-
-
-
-
- Il campo Denominazione è in alternativa ai campi Nome e Cognome
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati del Rappresentante Fiscale
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati del Cessionario / Committente
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati di Beni Servizi della Fattura Elettronica
-
-
-
-
-
-
-
-
- Blocco relativo ai dati dei Veicoli della Fattura Elettronica (da indicare nei casi di cessioni tra Paesi membri di mezzi di trasporto nuovi, in base all'art. 38, comma 4 del dl 331 del 1993)
-
-
-
-
-
-
-
-
- Blocco relativo ai dati di Pagamento della Fattura Elettronica
-
-
-
-
-
-
-
-
-
-
-
-
- pagamento a rate
-
-
-
-
- pagamento completo
-
-
-
-
- anticipo
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- contanti
-
-
-
-
- assegno
-
-
-
-
- assegno circolare
-
-
-
-
- contanti presso Tesoreria
-
-
-
-
- bonifico
-
-
-
-
- vaglia cambiario
-
-
-
-
- bollettino bancario
-
-
-
-
- carta di pagamento
-
-
-
-
- RID
-
-
-
-
- RID utenze
-
-
-
-
- RID veloce
-
-
-
-
- RIBA
-
-
-
-
- MAV
-
-
-
-
- quietanza erario
-
-
-
-
- giroconto su conti di contabilità speciale
-
-
-
-
- domiciliazione bancaria
-
-
-
-
- domiciliazione postale
-
-
-
-
- bollettino di c/c postale
-
-
-
-
- SEPA Direct Debit
-
-
-
-
- SEPA Direct Debit CORE
-
-
-
-
- SEPA Direct Debit B2B
-
-
-
-
- Trattenuta su somme già riscosse
-
-
-
-
- PagoPA
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati del Terzo Intermediario che emette fattura elettronica per conto del Cedente/Prestatore
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Blocco relativo ai dati di eventuali allegati
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SI = Cessione / Prestazione soggetta a ritenuta
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- esigibilità differita
-
-
-
-
- esigibilità immediata
-
-
-
-
- scissione dei pagamenti
-
-
-
-
-
-
-
-
- Escluse ex. art. 15 del D.P.R. 633/1972
-
-
-
-
-
- Non soggette
-
-
-
-
- Non soggette ad IVA ai sensi degli artt. da 7 a 7-septies del DPR 633/72
-
-
-
-
- Non soggette - altri casi
-
-
-
-
-
- Non imponibili
-
-
-
-
- Non Imponibili - esportazioni
-
-
-
-
- Non Imponibili - cessioni intracomunitarie
-
-
-
-
- Non Imponibili - cessioni verso San Marino
-
-
-
-
- Non Imponibili - operazioni assimilate alle cessioni all'esportazione
-
-
-
-
- Non Imponibili - a seguito di dichiarazioni d'intento
-
-
-
-
- Non Imponibili - altre operazioni che non concorrono alla formazione del plafond
-
-
-
-
- Esenti
-
-
-
-
- Regime del margine/IVA non esposta in fattura
-
-
-
-
-
- Inversione contabile (per le operazioni in reverse charge ovvero nei casi di autofatturazione per acquisti extra UE di servizi ovvero per importazioni di beni nei soli casi previsti)
-
-
-
-
- Inversione contabile - cessione di rottami e altri materiali di recupero
-
-
-
-
- Inversione contabile - cessione di oro e argento ai sensi della legge 7/2000 nonché di oreficeria usata ad OPO
-
-
-
-
- Inversione contabile - subappalto nel settore edile
-
-
-
-
- Inversione contabile - cessione di fabbricati
-
-
-
-
- Inversione contabile - cessione di telefoni cellulari
-
-
-
-
- Inversione contabile - cessione di prodotti elettronici
-
-
-
-
- Inversione contabile - prestazioni comparto edile e settori connessi
-
-
-
-
- Inversione contabile - operazioni settore energetico
-
-
-
-
- Inversione contabile - altri casi
-
-
-
-
- IVA assolta in altro stato UE (prestazione di servizi di telecomunicazioni, tele-radiodiffusione ed elettronici ex art. 7-octies lett. a, b, art. 74-sexies DPR 633/72)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- socio unico
-
-
-
-
- più soci
-
-
-
-
-
-
-
-
- in liquidazione
-
-
-
-
- non in liquidazione
-
-
-
-
-
-
-
-
-
- Sconto
-
-
-
-
- Premio
-
-
-
-
- Abbuono
-
-
-
-
- Spesa accessoria
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/data/schema/Schema_del_file_xml_FatturaPA_v1.2.2.xsd b/schemas/FatturaPA_v1.2.2.xsd
similarity index 66%
rename from test/data/schema/Schema_del_file_xml_FatturaPA_v1.2.2.xsd
rename to schemas/FatturaPA_v1.2.2.xsd
index fb48a77..264790f 100644
--- a/test/data/schema/Schema_del_file_xml_FatturaPA_v1.2.2.xsd
+++ b/schemas/FatturaPA_v1.2.2.xsd
@@ -1,11 +1,11 @@
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
+ targetNamespace="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
+ version="1.2.2">
-
+
@@ -15,30 +15,32 @@
-
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
@@ -46,13 +48,13 @@
Blocco relativo ai dati di trasmissione della Fattura Elettronica
-
-
-
-
+
+
+
+
-
-
+
+
@@ -61,8 +63,8 @@
-
-
+
+
@@ -74,95 +76,101 @@
-
-
- Fattura verso PA
-
-
-
-
- Fattura verso privati
-
-
+
+
+ Fattura verso PA
+
+
+
+
+ Fattura verso privati
+
+
-
+
-
- Blocco relativo ai Dati Generali della Fattura Elettronica
-
+ Blocco relativo ai Dati Generali della Fattura Elettronica
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
+
@@ -185,7 +193,8 @@
-
+
@@ -215,7 +224,8 @@
- SI = Documento emesso secondo modalità e termini stabiliti con DM ai sensi dell'art. 73 DPR 633/72
+ SI = Documento emesso secondo modalità e termini stabiliti con DM ai
+ sensi dell'art. 73 DPR 633/72
@@ -240,7 +250,8 @@
- Cassa nazionale previdenza e assistenza ingegneri e architetti liberi professionisti
+ Cassa nazionale previdenza e assistenza ingegneri e architetti liberi
+ professionisti
@@ -255,7 +266,8 @@
- Ente nazionale assistenza agenti e rappresentanti di commercio (ENASARCO)
+ Ente nazionale assistenza agenti e rappresentanti di commercio
+ (ENASARCO)
@@ -280,7 +292,8 @@
- Ente nazionale previdenza e assistenza impiegati dell'agricoltura (ENPAIA)
+ Ente nazionale previdenza e assistenza impiegati dell'agricoltura
+ (ENPAIA)
@@ -320,7 +333,8 @@
- Ente nazionale previdenza e assistenza professione infermieristica (ENPAPI)
+ Ente nazionale previdenza e assistenza professione infermieristica
+ (ENPAPI)
@@ -390,7 +404,8 @@
- Autofattura per regolarizzazione e integrazione delle fatture (ex art.6 c.8 e 9-bis d.lgs.471/97 o art.46 c.5 D.L. 331/93
+ Autofattura per regolarizzazione e integrazione delle fatture (ex art.6
+ c.8 e 9-bis d.lgs.471/97 o art.46 c.5 D.L. 331/93
@@ -410,17 +425,20 @@
- Fattura differita di cui all'art.21, comma 4, terzo periodo lett. a) DPR 633/72
+ Fattura differita di cui all'art.21, comma 4, terzo periodo lett. a) DPR
+ 633/72
- Fattura differita di cui all'art.21, comma 4, terzo periodo lett. b) DPR 633/72
+ Fattura differita di cui all'art.21, comma 4, terzo periodo lett. b) DPR
+ 633/72
- Cessione di beni ammortizzabili e per passaggi interni (ex art.36 DPR 633/72)
+ Cessione di beni ammortizzabili e per passaggi interni (ex art.36 DPR
+ 633/72)
@@ -477,13 +495,14 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -494,42 +513,43 @@
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
@@ -552,24 +572,24 @@
Blocco relativo ai dati del Cedente / Prestatore
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -587,7 +607,8 @@
- Agricoltura e attività connesse e pesca (artt. 34 e 34-bis, D.P.R. 633/1972)
+ Agricoltura e attività connesse e pesca (artt. 34 e 34-bis, D.P.R.
+ 633/1972)
@@ -607,17 +628,20 @@
- Gestione di servizi di telefonia pubblica (art. 74, c.1, D.P.R. 633/1972)
+ Gestione di servizi di telefonia pubblica (art. 74, c.1, D.P.R.
+ 633/1972)
- Rivendita di documenti di trasporto pubblico e di sosta (art. 74, c.1, D.P.R. 633/1972)
+ Rivendita di documenti di trasporto pubblico e di sosta (art. 74, c.1,
+ D.P.R. 633/1972)
- Intrattenimenti, giochi e altre attività di cui alla tariffa allegata al D.P.R. 640/72 (art. 74, c.6, D.P.R. 633/1972)
+ Intrattenimenti, giochi e altre attività di cui alla tariffa allegata al
+ D.P.R. 640/72 (art. 74, c.6, D.P.R. 633/1972)
@@ -637,12 +661,14 @@
- Rivendita di beni usati, di oggetti d’arte, d’antiquariato o da collezione (art. 36, D.L. 41/1995)
+ Rivendita di beni usati, di oggetti d’arte, d’antiquariato o da
+ collezione (art. 36, D.L. 41/1995)
- Agenzie di vendite all’asta di oggetti d’arte, antiquariato o da collezione (art. 40-bis, D.L. 41/1995)
+ Agenzie di vendite all’asta di oggetti d’arte, antiquariato o da
+ collezione (art. 40-bis, D.L. 41/1995)
@@ -655,7 +681,7 @@
IVA per cassa (art. 32-bis, D.L. 83/2012)
-
+
Regime forfettario
@@ -674,44 +700,44 @@
-
+
-
-
+
+
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
- Blocco relativo ai dati del Rappresentante Fiscale
+ Blocco relativo ai dati del Rappresentante Fiscale
@@ -719,9 +745,9 @@
-
+
-
+
@@ -729,49 +755,51 @@
Blocco relativo ai dati del Cessionario / Committente
-
-
-
-
+
+
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
- Blocco relativo ai dati di Beni Servizi della Fattura Elettronica
+ Blocco relativo ai dati di Beni Servizi della Fattura Elettronica
-
+
- Blocco relativo ai dati dei Veicoli della Fattura Elettronica (da indicare nei casi di cessioni tra Paesi
- membri di mezzi di trasporto nuovi, in base all'art. 38, comma 4 del dl 331 del 1993)
+ Blocco relativo ai dati dei Veicoli della Fattura Elettronica (da indicare
+ nei casi di cessioni tra Paesi membri di mezzi di trasporto nuovi, in base all'art. 38,
+ comma 4 del dl 331 del 1993)
-
+
@@ -780,8 +808,8 @@
Blocco relativo ai dati di Pagamento della Fattura Elettronica
-
-
+
+
@@ -807,27 +835,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -962,7 +990,8 @@
- Blocco relativo ai dati del Terzo Intermediario che emette fattura elettronica per conto del Cedente/Prestatore
+ Blocco relativo ai dati del Terzo Intermediario che emette fattura
+ elettronica per conto del Cedente/Prestatore
@@ -970,9 +999,9 @@
-
+
-
+
@@ -980,45 +1009,48 @@
Blocco relativo ai dati di eventuali allegati
-
-
-
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
-
+
@@ -1033,13 +1065,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -1071,7 +1103,8 @@
Escluse ex. art. 15 del D.P.R. 633/1972
-
+
Non soggette
@@ -1087,7 +1120,8 @@
Non soggette - altri casi
-
+
Non imponibili
@@ -1120,7 +1154,8 @@
- Non Imponibili - altre operazioni che non concorrono alla formazione del plafond
+ Non Imponibili - altre operazioni che non concorrono alla formazione del
+ plafond
@@ -1133,10 +1168,13 @@
Regime del margine/IVA non esposta in fattura
-
+
- Inversione contabile (per le operazioni in reverse charge ovvero nei casi di autofatturazione per acquisti extra UE di servizi ovvero per importazioni di beni nei soli casi previsti)
+ Inversione contabile (per le operazioni in reverse charge ovvero nei
+ casi di autofatturazione per acquisti extra UE di servizi ovvero per importazioni di
+ beni nei soli casi previsti)
@@ -1146,7 +1184,8 @@
- Inversione contabile - cessione di oro e argento ai sensi della legge 7/2000 nonché di oreficeria usata ad OPO
+ Inversione contabile - cessione di oro e argento ai sensi della legge
+ 7/2000 nonché di oreficeria usata ad OPO
@@ -1186,7 +1225,9 @@
- IVA assolta in altro stato UE (prestazione di servizi di telecomunicazioni, tele-radiodiffusione ed elettronici ex art. 7-octies lett. a, b, art. 74-sexies DPR 633/72)
+ IVA assolta in altro stato UE (prestazione di servizi di
+ telecomunicazioni, tele-radiodiffusione ed elettronici ex art. 7-octies lett. a, b, art.
+ 74-sexies DPR 633/72)
@@ -1370,7 +1411,8 @@
-
+
@@ -1380,7 +1422,8 @@
-
+
@@ -1451,4 +1494,4 @@
-
+
\ No newline at end of file
diff --git a/schema/ST Fatturazione elettronica - Schema VFSM10_Schema_VFSM10.xsd b/schemas/SVFSM10.xsd
similarity index 100%
rename from schema/ST Fatturazione elettronica - Schema VFSM10_Schema_VFSM10.xsd
rename to schemas/SVFSM10.xsd
diff --git a/test/data/schema/xmldsig-core-schema.xsd b/schemas/xmldsig-core.xsd
similarity index 100%
rename from test/data/schema/xmldsig-core-schema.xsd
rename to schemas/xmldsig-core.xsd
diff --git a/test/data/invoice-b2g.json b/test/data/invoice-b2g.json
new file mode 100644
index 0000000..121b2f8
--- /dev/null
+++ b/test/data/invoice-b2g.json
@@ -0,0 +1,185 @@
+{
+ "$schema": "https://gobl.org/draft-0/envelope",
+ "head": {
+ "uuid": "019270f1-b0d8-7299-85ca-0a595a9ee9c7",
+ "dig": {
+ "alg": "sha256",
+ "val": "eed68971ecbfb14d4396d12bb91b7f390a7e34bbfcf02ad85e533e9c2082d43e"
+ }
+ },
+ "doc": {
+ "$schema": "https://gobl.org/draft-0/bill/invoice",
+ "$regime": "IT",
+ "$addons": [
+ "it-sdi-v1"
+ ],
+ "$tags": [
+ "b2g"
+ ],
+ "uuid": "0190caea-c344-7afa-a530-252b67108176",
+ "type": "standard",
+ "series": "SAMPLE",
+ "code": "002",
+ "issue_date": "2024-10-09",
+ "currency": "EUR",
+ "tax": {
+ "ext": {
+ "it-sdi-document-type": "TD01",
+ "it-sdi-format": "FPA12"
+ }
+ },
+ "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"
+ },
+ "ext": {
+ "it-sdi-fiscal-regime": "RF01"
+ }
+ },
+ "customer": {
+ "name": "Mela S.r.l.",
+ "tax_id": {
+ "country": "IT",
+ "code": "13029381004"
+ },
+ "inboxes": [
+ {
+ "key": "codice-destinatario",
+ "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"
+ },
+ "sum": "1.00",
+ "taxes": [
+ {
+ "cat": "VAT",
+ "rate": "exempt",
+ "ext": {
+ "it-sdi-exempt": "N1"
+ }
+ }
+ ],
+ "total": "1.00"
+ },
+ {
+ "i": 2,
+ "quantity": "2",
+ "item": {
+ "name": "Camera Matrimoniale",
+ "price": "125.00"
+ },
+ "sum": "250.00",
+ "discounts": [
+ {
+ "amount": "10.00",
+ "reason": "Sconto"
+ }
+ ],
+ "taxes": [
+ {
+ "cat": "VAT",
+ "rate": "intermediate",
+ "percent": "10.0%"
+ }
+ ],
+ "total": "240.00"
+ }
+ ],
+ "ordering": {
+ "purchases": [
+ {
+ "code": "ORDINECLI",
+ "identities": [
+ {
+ "type": "CIG",
+ "code": "ZB98B4A235"
+ }
+ ]
+ }
+ ]
+ },
+ "payment": {
+ "advances": [
+ {
+ "date": "2023-05-01",
+ "key": "card",
+ "description": "deposit",
+ "percent": "100%",
+ "amount": "265.00",
+ "ext": {
+ "it-sdi-payment-means": "MP08"
+ }
+ }
+ ]
+ },
+ "totals": {
+ "sum": "241.00",
+ "total": "241.00",
+ "taxes": {
+ "categories": [
+ {
+ "code": "VAT",
+ "rates": [
+ {
+ "key": "exempt",
+ "ext": {
+ "it-sdi-exempt": "N1"
+ },
+ "base": "1.00",
+ "amount": "0.00"
+ },
+ {
+ "key": "intermediate",
+ "base": "240.00",
+ "percent": "10.0%",
+ "amount": "24.00"
+ }
+ ],
+ "amount": "24.00"
+ }
+ ],
+ "sum": "24.00"
+ },
+ "tax": "24.00",
+ "total_with_tax": "265.00",
+ "payable": "265.00",
+ "advance": "265.00",
+ "due": "0.00"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/data/invoice-credit-note.json b/test/data/invoice-credit-note.json
new file mode 100644
index 0000000..ef5e216
--- /dev/null
+++ b/test/data/invoice-credit-note.json
@@ -0,0 +1,229 @@
+{
+ "$schema": "https://gobl.org/draft-0/envelope",
+ "head": {
+ "uuid": "019270f3-513e-71d2-bec3-991386b87615",
+ "dig": {
+ "alg": "sha256",
+ "val": "6f813cd3986583ece8e9722d7f6419796dd99c9661d417350680a3290dc5f065"
+ }
+ },
+ "doc": {
+ "$schema": "https://gobl.org/draft-0/bill/invoice",
+ "$regime": "IT",
+ "$addons": [
+ "it-sdi-v1"
+ ],
+ "$tags": [
+ "freelance"
+ ],
+ "uuid": "019270f3-513e-71e2-b2e3-47f8321a09ac",
+ "type": "credit-note",
+ "series": "CN",
+ "code": "001",
+ "issue_date": "2024-10-09",
+ "currency": "EUR",
+ "preceding": [
+ {
+ "uuid": "0190c0ec-8109-756b-a4f0-88c4b542ab6e",
+ "type": "standard",
+ "issue_date": "2023-03-02",
+ "series": "SAMPLE",
+ "code": "001"
+ }
+ ],
+ "tax": {
+ "ext": {
+ "it-sdi-document-type": "TD04",
+ "it-sdi-format": "FPR12"
+ }
+ },
+ "supplier": {
+ "name": "MªF. Services",
+ "tax_id": {
+ "country": "IT",
+ "code": "12345678903"
+ },
+ "people": [
+ {
+ "name": {
+ "given": "GIANCARLO",
+ "surname": "ROSSI"
+ }
+ }
+ ],
+ "addresses": [
+ {
+ "num": "1",
+ "street": "VIALE DELLA LIBERTÀ",
+ "locality": "ROMA",
+ "region": "RM",
+ "code": "00100",
+ "country": "IT"
+ }
+ ],
+ "emails": [
+ {
+ "addr": "billing@example.com"
+ }
+ ],
+ "telephones": [
+ {
+ "num": "999999999"
+ }
+ ],
+ "registration": {
+ "capital": "50000.00",
+ "currency": "EUR",
+ "office": "RM",
+ "entry": "123456"
+ },
+ "ext": {
+ "it-sdi-fiscal-regime": "RF02"
+ }
+ },
+ "customer": {
+ "name": "MARIO LEONI",
+ "tax_id": {
+ "country": "IT",
+ "code": "09876543217"
+ },
+ "people": [
+ {
+ "name": {
+ "prefix": "Dott.",
+ "given": "MARIO",
+ "surname": "LEONI"
+ }
+ }
+ ],
+ "inboxes": [
+ {
+ "key": "it-sdi-code",
+ "code": "ABCDEF1"
+ }
+ ],
+ "addresses": [
+ {
+ "num": "32",
+ "street": "VIALE DELI LAVORATORI",
+ "locality": "FIRENZE",
+ "region": "FI",
+ "code": "50100",
+ "country": "IT"
+ }
+ ],
+ "emails": [
+ {
+ "addr": "leoni@mario.com"
+ }
+ ]
+ },
+ "lines": [
+ {
+ "i": 1,
+ "quantity": "20",
+ "item": {
+ "name": "Development services",
+ "price": "90.00",
+ "unit": "h"
+ },
+ "sum": "1800.00",
+ "discounts": [
+ {
+ "percent": "10%",
+ "amount": "180.00",
+ "reason": "Special discount"
+ }
+ ],
+ "taxes": [
+ {
+ "cat": "VAT",
+ "rate": "standard",
+ "percent": "22.0%"
+ }
+ ],
+ "total": "1620.00"
+ },
+ {
+ "i": 2,
+ "quantity": "1",
+ "item": {
+ "name": "Special Untaxed Work",
+ "price": "100.00",
+ "unit": "h"
+ },
+ "sum": "100.00",
+ "taxes": [
+ {
+ "cat": "VAT",
+ "rate": "exempt",
+ "ext": {
+ "it-sdi-exempt": "N2.2"
+ }
+ }
+ ],
+ "total": "100.00"
+ }
+ ],
+ "discounts": [
+ {
+ "i": 1,
+ "base": "1720.00",
+ "percent": "50%",
+ "amount": "860.00",
+ "reason": "10th year anniversary discount"
+ }
+ ],
+ "charges": [
+ {
+ "i": 1,
+ "base": "1720.00",
+ "percent": "10%",
+ "amount": "172.00",
+ "reason": "10th year anniversary charge"
+ }
+ ],
+ "payment": {
+ "instructions": {
+ "key": "card",
+ "ext": {
+ "it-sdi-payment-means": "MP08"
+ }
+ }
+ },
+ "totals": {
+ "sum": "1720.00",
+ "discount": "860.00",
+ "charge": "172.00",
+ "total": "1032.00",
+ "taxes": {
+ "categories": [
+ {
+ "code": "VAT",
+ "rates": [
+ {
+ "key": "standard",
+ "base": "1620.00",
+ "percent": "22.0%",
+ "amount": "356.40"
+ },
+ {
+ "key": "exempt",
+ "ext": {
+ "it-sdi-exempt": "N2.2"
+ },
+ "base": "100.00",
+ "amount": "0.00"
+ }
+ ],
+ "amount": "356.40"
+ }
+ ],
+ "sum": "356.40"
+ },
+ "tax": "356.40",
+ "total_with_tax": "1388.40",
+ "payable": "1388.40"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/data/out/invoice-b2g.xml b/test/data/out/invoice-b2g.xml
new file mode 100644
index 0000000..f3b559b
--- /dev/null
+++ b/test/data/out/invoice-b2g.xml
@@ -0,0 +1,181 @@
+
+
+
+
+ IT
+ 01234567890
+
+ 019270f1
+ FPA12
+ 0000000
+
+
+
+
+ IT
+ 12345678903
+
+
+ Hotel California
+
+ RF01
+
+
+ Via California
+ 102
+ 33213
+ Palermo
+ PA
+ IT
+
+
+ RM
+ 123456
+ LN
+
+
+
+
+
+
+ IT
+ 13029381004
+
+
+ Mela S.r.l.
+
+
+
+ Via dei Mille
+ 23
+ 00100
+ Firenze
+ FI
+ IT
+
+
+
+
+
+
+ TD01
+ EUR
+ 2024-10-09
+ SAMPLE-002
+ 265.00
+
+
+ ORDINECLI
+ ZB98B4A235
+
+
+
+
+ 1
+ Tassa di Soggiorno
+ 1.00
+ 1.00
+ 1.00
+ 0.00
+ N1
+
+
+ 2
+ Camera Matrimoniale
+ 2.00
+ 125.00
+
+ SC
+ 5.00
+
+ 240.00
+ 10.00
+
+
+ 0.00
+ N1
+ 1.00
+ 0.00
+ Escluse ex. art. 15 del D.P.R. 633/1972
+
+
+ 10.00
+ 240.00
+ 24.00
+
+
+
+ TP03
+
+ MP08
+ 2023-05-01
+ 265.00
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+ AQAB
+
+
+
+
+
+
+
+ 2022-02-01T04:00:00+00:00
+
+
+
+
+ VmNYwDiCBBXJX/IL1AUYj7uHouM2Jcp3ZkeqmB+FKGTTwXIIZnCWmZVhCSB7uNoV6Xee7nZVkMqeCMQk3tGR0g==
+
+
+ CN=AC FNMT Usuarios,OU=Ceres,O=FNMT-RCM,C=ES
+ 96891622000445695554354105786026700712
+
+
+
+
+
+
+ Fattura PA
+
+ urn:oid:1.2.840.10003.5.109.10
+
+
+ text/xml
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/data/out/invoice-credit-note.xml b/test/data/out/invoice-credit-note.xml
new file mode 100644
index 0000000..aabe732
--- /dev/null
+++ b/test/data/out/invoice-credit-note.xml
@@ -0,0 +1,195 @@
+
+
+
+
+ IT
+ 01234567890
+
+ 019270f3
+ FPR12
+ ABCDEF1
+
+
+
+
+ IT
+ 12345678903
+
+
+ MªF. Services
+
+ RF02
+
+
+ VIALE DELLA LIBERTÀ
+ 1
+ 00100
+ ROMA
+ RM
+ IT
+
+
+ RM
+ 123456
+ 50000.00
+ LN
+
+
+ 999999999
+ billing@example.com
+
+
+
+
+
+ IT
+ 09876543217
+
+
+ MARIO LEONI
+
+
+
+ VIALE DELI LAVORATORI
+ 32
+ 50100
+ FIRENZE
+ FI
+ IT
+
+
+
+
+
+
+ TD04
+ EUR
+ 2024-10-09
+ CN-001
+
+ SC
+ 50.00
+ 860.00
+
+
+ MG
+ 10.00
+ 172.00
+
+ 1388.40
+
+
+ SAMPLE-001
+ 2023-03-02
+
+
+
+
+ 1
+ Development services
+ 20.00
+ 90.00
+
+ SC
+ 10.00
+ 9.00
+
+ 1620.00
+ 22.00
+
+
+ 2
+ Special Untaxed Work
+ 1.00
+ 100.00
+ 100.00
+ 0.00
+ N2.2
+
+
+ 22.00
+ 1620.00
+ 356.40
+
+
+ 0.00
+ N2.2
+ 100.00
+ 0.00
+ Non soggette - altri casi
+
+
+
+ TP02
+
+ MP08
+ 1388.40
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+ AQAB
+
+
+
+
+
+
+
+ 2022-02-01T04:00:00+00:00
+
+
+
+
+ VmNYwDiCBBXJX/IL1AUYj7uHouM2Jcp3ZkeqmB+FKGTTwXIIZnCWmZVhCSB7uNoV6Xee7nZVkMqeCMQk3tGR0g==
+
+
+ CN=AC FNMT Usuarios,OU=Ceres,O=FNMT-RCM,C=ES
+ 96891622000445695554354105786026700712
+
+
+
+
+
+
+ Fattura PA
+
+ urn:oid:1.2.840.10003.5.109.10
+
+
+ text/xml
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/test.go b/test/test.go
index 0f0fb93..220e799 100644
--- a/test/test.go
+++ b/test/test.go
@@ -3,6 +3,7 @@
package test
import (
+ "bytes"
"encoding/json"
"flag"
"os"
@@ -103,11 +104,27 @@ func LoadTestFile(file string) *gobl.Envelope {
panic(err)
}
- env, err := fatturapa.UnmarshalGOBL(f)
+ buf := new(bytes.Buffer)
+ if _, err := buf.ReadFrom(f); err != nil {
+ panic(err)
+ }
+
+ out, err := gobl.Parse(buf.Bytes())
if err != nil {
panic(err)
}
+ var env *gobl.Envelope
+ switch doc := out.(type) {
+ case *gobl.Envelope:
+ env = doc
+ default:
+ env = gobl.NewEnvelope()
+ if err := env.Insert(doc); err != nil {
+ panic(err)
+ }
+ }
+
if err := env.Calculate(); err != nil {
panic(err)
}
@@ -132,7 +149,7 @@ func LoadTestFile(file string) *gobl.Envelope {
// LoadSchema loads a XSD schema for validating XML documents
func LoadSchema() (*xsd.Schema, error) {
- schemaPath := filepath.Join(GetDataPath(), "schema", "Schema_del_file_xml_FatturaPA_v1.2.2.xsd")
+ schemaPath := filepath.Join("schemas", "FatturaPA_v1.2.2.xsd")
schema, err := xsd.ParseFromFile(schemaPath)
if err != nil {
return nil, err