Skip to main content

parse and generate Italian Fattura Elettronica

Project description

Python A38

full workflow

Library to generate Italian Fattura Elettronica from Python.

This library implements a declarative data model similar to Django models, that is designed to describe, validate, serialize and parse Italian Fattura Elettronica data.

Only part of the specification is implemented, with more added as needs will arise. You are welcome to implement the missing pieces you need and send a pull request: the idea is to have a good, free (as in freedom) library to make billing in Italy with Python easier for everyone.

The library can generate various kinds of fatture that pass validation, and can parse all the example XML files distributed by fatturapa.gov.it

Dependencies

Required: dateutil, pytz, asn1crypto, and the python3 standard library.

Optional:

  • yapf for formatting a38tool python output
  • lxml for rendering to HTML
  • the wkhtmltopdf command for rendering to PDF
  • requests for downloading CA certificates for signature verification

a38tool script

A simple command line wrapper to the library functions is available as a38tool:

$ a38tool --help
usage: a38tool [-h] [--verbose] [--debug]
               {json,xml,python,diff,validate,html,pdf,update_capath} ...

Handle fattura elettronica files

positional arguments:
  {json,xml,python,diff,validate,html,pdf,update_capath}
                        actions
    json                output a fattura in JSON
    xml                 output a fattura in XML
    python              output a fattura as Python code
    diff                show the difference between two fatture
    validate            validate the contents of a fattura
    html                render a Fattura as HTML using a .xslt stylesheet
    pdf                 render a Fattura as PDF using a .xslt stylesheet
    update_capath       create/update an openssl CApath with CA certificates
                        that can be used to validate digital signatures

optional arguments:
  -h, --help            show this help message and exit
  --verbose, -v         verbose output
  --debug               debug output

See a38tool.md for more details.

Example code

import a38
from a38.validation import Validation
import datetime
import sys

cedente_prestatore = a38.CedentePrestatore(
    a38.DatiAnagraficiCedentePrestatore(
        a38.IdFiscaleIVA("IT", "01234567890"),
        codice_fiscale="NTNBLN22C23A123U",
        anagrafica=a38.Anagrafica(denominazione="Test User"),
        regime_fiscale="RF01",
    ),
    a38.Sede(indirizzo="via Monferrato", numero_civico="1", cap="50100", comune="Firenze", provincia="FI", nazione="IT"),
    iscrizione_rea=a38.IscrizioneREA(
        ufficio="FI",
        numero_rea="123456",
        stato_liquidazione="LN",
    ),
    contatti=a38.Contatti(email="local_part@pec_domain.it"),
)

cessionario_committente = a38.CessionarioCommittente(
    a38.DatiAnagraficiCessionarioCommittente(
        a38.IdFiscaleIVA("IT", "76543210987"),
        anagrafica=a38.Anagrafica(denominazione="A Company SRL"),
    ),
    a38.Sede(indirizzo="via Langhe", numero_civico="1", cap="50142", comune="Firenze", provincia="FI", nazione="IT"),
)

bill_number = 1

f = a38.FatturaPrivati12()
f.fattura_elettronica_header.dati_trasmissione.id_trasmittente = a38.IdTrasmittente("IT", "10293847561")
f.fattura_elettronica_header.dati_trasmissione.codice_destinatario = "FUFUFUF"
f.fattura_elettronica_header.cedente_prestatore = cedente_prestatore
f.fattura_elettronica_header.cessionario_committente = cessionario_committente

body = f.fattura_elettronica_body[0]
body.dati_generali.dati_generali_documento = a38.DatiGeneraliDocumento(
    tipo_documento="TD01",
    divisa="EUR",
    data=datetime.date.today(),
    numero=bill_number,
    causale=["Test billing"],
)

body.dati_beni_servizi.add_dettaglio_linee(
    descrizione="Test item", quantita=2, unita_misura="kg",
    prezzo_unitario="25.50", aliquota_iva="22.00")

body.dati_beni_servizi.add_dettaglio_linee(
    descrizione="Other item", quantita=1, unita_misura="kg",
    prezzo_unitario="15.50", aliquota_iva="22.00")

body.dati_beni_servizi.build_dati_riepilogo()
body.build_importo_totale_documento()

res = Validation()
f.validate(res)
if res.warnings:
    for w in res.warnings:
        print(str(w), file=sys.stderr)
if res.errors:
    for e in res.errors:
        print(str(e), file=sys.stderr)

filename = "{}{}_{:05d}.xml".format(
    f.fattura_elettronica_header.cedente_prestatore.dati_anagrafici.id_fiscale_iva.id_paese,
    f.fattura_elettronica_header.cedente_prestatore.dati_anagrafici.id_fiscale_iva.id_codice,
    bill_number)

tree = f.build_etree()
with open(filename, "wb") as out:
    tree.write(out, encoding="utf-8", xml_declaration=True)

Digital signatures

Digital signatures on Firma Elettronica are CAdES signatures.

openssl cal verify the signatures, but not yet generate them. A patch to sign with CAdES has been recently merged but not yet released as of 2019-02-26.

Downloading CA certificates

CA certificates for validating digital certificates are distributed by the EU in XML format. See also the AGID page about it.

There is a Trusted List Browser but apparently no way of getting a simple bundle of certificates useable by openssl.

a38tool has basic features to download and parse CA certificate information, and maintain a CA certificate directory:

a38tool update_capath certdir/ --remove-old

No particular effort is made to validate the downloaded certificates, besides the standard HTTPS checks performed by the requests library.

Verifying signed .p7m files

Once you have a CA certificate directory, verifying signed p7m files is quite straightforward:

openssl cms -verify -in tests/data/test.txt.p7m -inform der -CApath certs/

Useful links

XSLT stylesheets for displaying fatture:

Copyright

Copyright 2019-2022 Truelite S.r.l.

This software is released under the Apache License 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

a38-decimal-0.1.6.tar.gz (52.8 kB view details)

Uploaded Source

Built Distribution

a38_decimal-0.1.6-py3-none-any.whl (40.6 kB view details)

Uploaded Python 3

File details

Details for the file a38-decimal-0.1.6.tar.gz.

File metadata

  • Download URL: a38-decimal-0.1.6.tar.gz
  • Upload date:
  • Size: 52.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.10

File hashes

Hashes for a38-decimal-0.1.6.tar.gz
Algorithm Hash digest
SHA256 e75e68d4487af2eccc259fa3ad4f4b964eae6fce91d3f7e7aad3e0ea482db174
MD5 fbe92cb56ae0513d2912642ed66c50a3
BLAKE2b-256 1154f6a5bdb934f2bd9df5fb7b00c4d7ea452e2888cdc5803f415ad47d194a76

See more details on using hashes here.

File details

Details for the file a38_decimal-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: a38_decimal-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 40.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.0 CPython/3.9.10

File hashes

Hashes for a38_decimal-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 0d1512812fb344435abf0470e24d852d6502bc968212151007aa43be061a34a7
MD5 9de9520e71e6c5d37abe7c0c926c7b11
BLAKE2b-256 3d1efab67680d86cc63dacaa9717fda2cb3b7310e5bc6a36d895942845790bc7

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page