-
Notifications
You must be signed in to change notification settings - Fork 0
Home
🇬🇧 English first · 🇪🇸 Español más abajo
A zero-dependency Python library that builds Facturae 3.2.2 invoices — the Spanish electronic invoice format required for invoicing the public sector through FACe.
It produces a valid, unsigned document. Signing is not here, and Design decisions explains why that is a decision and not an omission.
| Page | What you will find |
|---|---|
| The invoice model | How the object model maps to the XML, the tax codes, and why totals cannot disagree with the lines |
| Design decisions | Why money is Decimal, why unknown JSON keys are an error, and why the library stops before the signature |
Task-oriented documentation — installing, the CLI, the JSON format, signing and
FACe — lives in the
docs/ folder.
This wiki covers the why; docs/ covers the how.
flowchart LR
A[Your data] --> B["Factura object<br/>(or JSON)"]
B --> C[validation]
C --> D["totals computed<br/>from the lines"]
D --> E["Facturae 3.2.2 XML<br/>unsigned"]
E -.->|"your signing step<br/>XAdES"| F[FACe]
style F stroke-dasharray: 5 5
The dashed part is deliberately outside the library.
What it does
- Models an invoice — issuer, recipient, lines, taxes — as plain Python objects
with type hints and a shipped
py.typed. - Computes the totals from the lines. They are not fields you fill in, so they cannot disagree with the detail.
- Generates Facturae 3.2.2 XML, and can also hand you the element tree if you need to post-process it.
- Round-trips through JSON (
desde_json/a_dict), which is what makes it usable from a language that is not Python. - Ships a CLI —
plantilla,validar,totales,generar,autocomprobar— every one of which reads-as stdin, so it composes withjqand friends.
What it does not do
-
It does not sign. Facturae requires an XAdES signature before it can be
submitted, and this library stops at the document. Handling a private key
belongs in your application's security model, and a signature library would
end the zero-dependency guarantee. A library that produced almost a
signature would be worse than one that is clear about where it stops.
See
docs/signing.md. - It does not submit anything to FACe.
- It does not decide your tax treatment. You say which tax applies; it formats and totals it.
Verified. 66 tests, 91 % statement coverage, ruff clean, and a runtime
autocomprobar that recomputes a hand-written invoice — 1 250,00 net,
262,50 output VAT, 150,00 withheld, 1 362,50 total — so a broken install fails
loudly.
Biblioteca de Python sin dependencias que construye facturas Facturae 3.2.2, el formato de factura electrónica española exigido para facturar al sector público a través de FACe.
Produce un documento válido y sin firmar. La firma no está aquí, y Design decisions explica por qué eso es una decisión y no un olvido.
| Página | Qué encontrarás |
|---|---|
| The invoice model | Cómo se corresponde el modelo de objetos con el XML, los códigos de impuesto y por qué los totales no pueden discrepar de las líneas |
| Design decisions | Por qué el dinero es Decimal, por qué una clave JSON desconocida es un error y por qué la biblioteca se detiene antes de la firma |
La documentación de uso —instalación, CLI, formato JSON, firma y FACe— está en
la carpeta docs/.
Esta wiki cuenta el porqué; docs/ cuenta el cómo.
flowchart LR
A[Tus datos] --> B["objeto Factura<br/>(o JSON)"]
B --> C[validación]
C --> D["totales calculados<br/>desde las líneas"]
D --> E["XML Facturae 3.2.2<br/>sin firmar"]
E -.->|"tu paso de firma<br/>XAdES"| F[FACe]
style F stroke-dasharray: 5 5
La parte discontinua queda fuera de la biblioteca a propósito.
Lo que hace
- Modela una factura —emisor, receptor, líneas, impuestos— como objetos de
Python normales, con anotaciones de tipo y un
py.typedincluido. - Calcula los totales a partir de las líneas. No son campos que rellenes, así que no pueden discrepar del detalle.
- Genera XML Facturae 3.2.2, y también puede devolverte el árbol de elementos si necesitas post-procesarlo.
- Va y vuelve por JSON (
desde_json/a_dict), que es lo que la hace utilizable desde un lenguaje que no sea Python. - Trae una CLI —
plantilla,validar,totales,generar,autocomprobar— y todos los subcomandos leen-como entrada estándar, así que se combinan conjqy compañía.
Lo que no hace
-
No firma. Facturae exige una firma XAdES antes de poder presentarse, y
esta biblioteca se detiene en el documento. Manejar una clave privada le
corresponde al modelo de seguridad de tu aplicación, y una biblioteca de firma
acabaría con la garantía de cero dependencias. Una biblioteca que produjera
casi una firma sería peor que una que deja claro dónde para.
Ver
docs/signing.md. - No presenta nada en FACe.
- No decide tu tratamiento fiscal. Tú dices qué impuesto aplica; ella lo formatea y lo totaliza.
Verificado. 66 pruebas, 91 % de cobertura de sentencias, ruff limpio y un
autocomprobar en tiempo de ejecución que recalcula una factura escrita a mano
—1.250,00 de base, 262,50 de IVA repercutido, 150,00 de retención y 1.362,50
de total— para que una instalación rota falle de forma ruidosa.