From 46308281be8b3b9397be4559ea5e9e951c09149f Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Wed, 9 Oct 2024 11:17:16 +0000 Subject: [PATCH 1/3] Adding support for preceding and ordering document refs --- README.md | 7 +- body.go | 105 +- cmd/gobl.fatturapa/convert.go | 11 +- converter.go | 19 - go.mod | 2 +- go.sum | 6 + retained_taxes_test.go | 8 +- schema/fatturapav1_2_2.xsd | 1446 ----------------- .../FatturaPA_v1.2.2.xsd | 525 +++--- .../SVFSM10.xsd | 0 .../xmldsig-core.xsd | 0 test/data/invoice-b2g.json | 185 +++ test/data/invoice-credit-note.json | 229 +++ test/data/out/invoice-b2g.xml | 181 +++ test/data/out/invoice-credit-note.xml | 195 +++ test/test.go | 21 +- 16 files changed, 1200 insertions(+), 1740 deletions(-) delete mode 100644 schema/fatturapav1_2_2.xsd rename test/data/schema/Schema_del_file_xml_FatturaPA_v1.2.2.xsd => schemas/FatturaPA_v1.2.2.xsd (66%) rename schema/ST Fatturazione elettronica - Schema VFSM10_Schema_VFSM10.xsd => schemas/SVFSM10.xsd (100%) rename test/data/schema/xmldsig-core-schema.xsd => schemas/xmldsig-core.xsd (100%) create mode 100644 test/data/invoice-b2g.json create mode 100644 test/data/invoice-credit-note.json create mode 100644 test/data/out/invoice-b2g.xml create mode 100644 test/data/out/invoice-credit-note.xml 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..8ba4217 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.201.1-0.20241008163233-e408d03008c3 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..1cefa5b 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,12 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 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.201.1-0.20241008093608-3aaf722242c8 h1:BIvxAiM6JA7tKNjGuO625pdQ6yHScuJs3TkUxK8HQ8I= +github.com/invopop/gobl v0.201.1-0.20241008093608-3aaf722242c8/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU= +github.com/invopop/gobl v0.201.1-0.20241008095938-bfdee523f9a1 h1:leeTQ53S+mh0/fJD3c6M1uexqyDsoZzj7aLTV86DVmM= +github.com/invopop/gobl v0.201.1-0.20241008095938-bfdee523f9a1/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU= +github.com/invopop/gobl v0.201.1-0.20241008163233-e408d03008c3 h1:XPbPlYycWuTiXlEYXjBOZu5sUKhAZV2b2l9D5B/BsuM= +github.com/invopop/gobl v0.201.1-0.20241008163233-e408d03008c3/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 From d1e1dcc7a8a155939dafd173e3f67031055d3678 Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Mon, 14 Oct 2024 10:12:19 +0000 Subject: [PATCH 2/3] Using GOBL 0.202 release --- go.mod | 2 +- go.sum | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 8ba4217..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.201.1-0.20241008163233-e408d03008c3 + 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 1cefa5b..1b9398e 100644 --- a/go.sum +++ b/go.sum @@ -22,14 +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.201.1-0.20241008093608-3aaf722242c8 h1:BIvxAiM6JA7tKNjGuO625pdQ6yHScuJs3TkUxK8HQ8I= -github.com/invopop/gobl v0.201.1-0.20241008093608-3aaf722242c8/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU= -github.com/invopop/gobl v0.201.1-0.20241008095938-bfdee523f9a1 h1:leeTQ53S+mh0/fJD3c6M1uexqyDsoZzj7aLTV86DVmM= -github.com/invopop/gobl v0.201.1-0.20241008095938-bfdee523f9a1/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU= -github.com/invopop/gobl v0.201.1-0.20241008163233-e408d03008c3 h1:XPbPlYycWuTiXlEYXjBOZu5sUKhAZV2b2l9D5B/BsuM= -github.com/invopop/gobl v0.201.1-0.20241008163233-e408d03008c3/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= From ee4505c9c1d2cdfec35dcd1f2992ebaac4f99401 Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Mon, 14 Oct 2024 10:19:08 +0000 Subject: [PATCH 3/3] Upgrading lint action --- .github/workflows/lint.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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