Skip to content

Commit

Permalink
Merge pull request #23 from invopop/simplified-fix
Browse files Browse the repository at this point in the history
Simplified fix
  • Loading branch information
samlown authored Jan 29, 2024
2 parents 15fadf2 + 579cbde commit b99f8a1
Show file tree
Hide file tree
Showing 11 changed files with 802 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.52
version: v1.55
79 changes: 50 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,51 @@
# gobl.fatturapa
# GOBL to FatturaPA Tools

GOBL Conversion into FatturaPA in Italy
Convert GOBL into the Italy's FatturaPA format.

# GOBL to FatturaPA Toolkit
Copyright [Invopop Ltd.](https://invopop.com) 2023. Released publicly under the [Apache License Version 2.0](LICENSE). For commercial licenses please contact the [dev team at invopop](mailto:[email protected]). In order to accept contributions to this library we will require transferring copyrights to Invopop Ltd.

Convert GOBL documents into the Italy's FatturaPA format.
[![Lint](https://github.com/invopop/gobl.factturapa/actions/workflows/lint.yaml/badge.svg)](https://github.com/invopop/gobl.fatturapa/actions/workflows/lint.yaml)
[![Test Go](https://github.com/invopop/gobl.fatturapa/actions/workflows/test.yaml/badge.svg)](https://github.com/invopop/gobl.fatturapa/actions/workflows/test.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/invopop/gobl.fatturapa)](https://goreportcard.com/report/github.com/invopop/gobl.fatturapa)
[![GoDoc](https://godoc.org/github.com/invopop/gobl.fatturapa?status.svg)](https://godoc.org/github.com/invopop/gobl.fatturapa)
![Latest Tag](https://img.shields.io/github/v/tag/invopop/gobl.fatturapa)

TODO: copyright, license, build statuses
## Introduction

FatturaPA defines two versions of invoices:

- Ordinary invoices, `FatturaElettronica` types `FPA12` and `FPR12` defined in the v1.2 schema, usable for all sales.
- Simplified invoices, `FatturaElettronicaSemplificata` type `FSM10` defined in the v1.0 schema, with a reduced set of requirements but can only be used for sales of less then €400, as of writing. **Currently not supported!**

Unlike other tax regimes, Italy requires simplified invoices to include the customer's tax ID. For "cash register" style receipts locally called "Scontrinos", another format and API is used for this from approved hardware.

## Sources

You can find copies of the Italian FatturaPA schema in the [schemas folder](./schema).

- [Historical Documentation](https://www.fatturapa.gov.it/en/norme-e-regole/documentazione-fattura-elettronica/formato-fatturapa/)
- [Ordinary Schema V1.2.1 Spec Table View (EN)](https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2.1/Table-view-B2B-Ordinary-invoice.pdf) - by far the most comprehensible spec doc. Since the difference between 1.2.2 and 1.2.1 is minimal, this is perfectly usable.
- [Ordinary Schema V1.2.2 PDF (IT)](https://www.fatturapa.gov.it/export/documenti/Specifiche_tecniche_del_formato_FatturaPA_v1.3.1.pdf) - most up-to-date but difficult
- [XSD V1.2.2](https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2.2/Schema_del_file_xml_FatturaPA_v1.2.2.xsd)
- [XSD V1 (FSM10) - simplified invoices](https://www.agenziaentrate.gov.it/portale/documents/20143/288192/ST+Fatturazione+elettronica+-+Schema+VFSM10_Schema_VFSM10.xsd/010f1b41-6683-1b31-ba36-c8bced659c06)

## Limitations

The FatturaPA XML schema is quite large and complex. This library is not complete and only supports a subset of the schema. The current implementation is focused on the most common use cases.

- Simplified invoices are not currently supported (please get in touch if you need this).
- FatturaPA allows multiple invoices within the document, but this library only supports a single invoice per transmission.
- Only a subset of payment methods (ModalitaPagamento) are supported. See `payments.go` for the list of supported codes.

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

Expand Down Expand Up @@ -78,29 +117,28 @@ 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.
The command line interface can be useful for situations when you're using a language other than Golang in your application. Install with:

```bash
cd cmd/gobl.fatturapa
go build
go install github.com/invopop/gobl.fatturapa
```

Simply provide the input GOBL JSON file and output to a file or another application:

```bash
./gobl.fatturapa convert input.json output.xml
gobl.fatturapa convert input.json output.xml
```

If you have a digital certificate, run with:

```bash
./gobl.fatturapa convert -c cert.p12 -p password input.json output.xml
gobl.fatturapa convert -c cert.p12 -p password input.json output.xml
```

To include the transmitter information, add the `-T` flag and provide the _country code_ and the _tax ID_:

```bash
./gobl.fatturapa convert -T ES12345678 input.json output.xml
gobl.fatturapa convert -T ES12345678 input.json output.xml
```

The command also supports pipes:
Expand All @@ -111,7 +149,7 @@ cat input.json > ./gobl.fatturapa output.xml

## Notes

- In all cases Go structures have been written using the same naming from the XML style document. This means names are not repeated in tags and generally makes it a bit easier map the XML output to the internal structures.
- In all cases Go structures have been written using the same naming from the XML style document. This means names are not repeated in tags and generally makes it a bit easier to map the XML output to the internal structures.

## Integration Tests

Expand All @@ -122,20 +160,3 @@ mage -v TestConversion
```

Sample data sources are contained in the `/test/data` directory. JSON (for tests) documents are stored in the Git repository, but the XML must be generated using the above commands.

## Current Conversion Limitations

The FatturaPA XML schema is quite large and complex. This library is not complete and only supports a subset of the schema. The current implementation is focused on the most common use cases.

- FatturaPA allows multiple invoices within the document, but this library only supports a single invoice per transmission.
- Only a subset of payment methods (ModalitaPagamento) are supported. See `payments.go` for the list of supported codes.

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)
6 changes: 6 additions & 0 deletions body.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fatturapa

import (
"errors"
"fmt"

"github.com/invopop/gobl/bill"
Expand Down Expand Up @@ -92,6 +93,11 @@ func newDatiGenerali(inv *bill.Invoice) (*datiGenerali, error) {
return nil, err
}

switch codeTipoDocumento {
case "TD07", "TD08", "TD09":
return nil, errors.New("simplified invoices are not currently supported")
}

return &datiGenerali{
DatiGeneraliDocumento: &datiGeneraliDocumento{
TipoDocumento: codeTipoDocumento,
Expand Down
18 changes: 11 additions & 7 deletions items.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,23 @@ func generateLineDetails(inv *bill.Invoice) []*dettaglioLinee {
var dl []*dettaglioLinee

for _, line := range inv.Lines {
vatTax := line.Taxes.Get(tax.CategoryVAT)

dl = append(dl, &dettaglioLinee{
d := &dettaglioLinee{
NumeroLinea: strconv.Itoa(line.Index),
Descrizione: line.Item.Name,
Quantita: formatAmount(&line.Quantity),
PrezzoUnitario: formatAmount(&line.Item.Price),
PrezzoTotale: formatAmount(&line.Sum),
AliquotaIVA: formatPercentage(vatTax.Percent),
Natura: vatTax.Ext[it.ExtKeySDINature].String(),
ScontoMaggiorazione: extractLinePriceAdjustments(line),
})
}
if len(line.Taxes) > 0 {
vatTax := line.Taxes.Get(tax.CategoryVAT)
if vatTax != nil {
d.AliquotaIVA = formatPercentage(vatTax.Percent)
d.Natura = vatTax.Ext[it.ExtKeySDINature].String()
}
}

dl = append(dl, d)
}

return dl
Expand Down Expand Up @@ -114,7 +119,6 @@ func findRiferimentoNormativo(rateTotal *tax.RateTotal) string {
def := regime.ExtensionDef(it.ExtKeySDINature)

nature := rateTotal.Ext[it.ExtKeySDINature]

for _, c := range def.Codes {
if c.Code == nature {
return c.Name[i18n.IT]
Expand Down
5 changes: 4 additions & 1 deletion parties.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ func newCedentePrestatore(s *org.Party) *supplier {
}

func newCessionarioCommittente(c *org.Party) *customer {
nc := new(customer)
if c == nil {
return nil
}

nc := new(customer)
if len(c.Addresses) > 0 {
nc.Sede = newAddress(c.Addresses[0])
}
Expand Down
Loading

0 comments on commit b99f8a1

Please sign in to comment.