Tool-chain for generating EN16931 conforming invoices from popular spreadsheet formats or JSON.
You can currently create invoices in these formats:
urn:cen.eu:en16931:2017
urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended
, also known as ZUGFeRD-Extendedurn:cen.eu:en16931:2017
urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0
The service in its current state is meant to be run in a network with limited access or behind an API gateway that prevents abuse of the service.
One simple solution is to use ngninx
as a
gateway and configure rate-limiting there. You will also want to limit
the maximum request body size.
This repository is an attempt to aid small businesses, especially in France and Germany but also in other parts of the European Union to create electronic invoices conforming with EN16931 with only free and open-source software.
It is quite unlikely that you can use anything here out of the box. See it as a starter template for your own solution.
This README.md
is probably incomplete. Please see the blog post
Creating Electronic Invoices with Free and Open Source
Software
for more accurate in-depth information!
$ bun install --optional
This may warn about "husky" missing. Just run bun install
again in order
to fix this.
# development
$ bun run start
# watch mode
$ bun run start:dev
# production mode
$ bun run start:prod
# unit tests
$ bun run test
# e2e tests
$ bun run test:e2e
# test coverage
$ bun run test:cov
The following assumes that you run the application with start:dev
and the
API is exposed at http://localhost:3000.
curl http://localhost:3000/api
It probably makes more sense to open that URL in the browser.
$ curl http://localhost:3000/api/format/list
This will return a list with format informat. For each format, the name, the customization and profile ID, the MIME type, and the syntax (UBL or CII) is returned.
The application ships with a mapping in resources/default-invoice.yaml
.
You can use it with the spreadsheet data from
contrib/templates/1234567890-consulting/default-invoice.ods
like this:
$ curl -X POST http://localhost:3000/api/mapping/transform/UBL \
-F mapping=@contrib/mappings/default-invoice.yaml \
-F data=@contrib/templates/1234567890-consulting/default-invoice.ods
This will create invoice data in the internal format from a spreadsheet. The intended target format is UBL.
$ curl -v -X POST \
http://localhost:3000/api/invoice/transform-and-create/UBL \
-F mapping=@contrib/mappings/default-invoice.yaml \
-F data=@contrib/templates/1234567890-consulting/default-invoice.ods
This will transform the spreadsheet into the internal format and immediately
create an invoice in format UBL
.
The formats UBL
and XRECHNUNG-UBL
are currently the only supported formats.
Say you want to add a PDF version invoice.pdf
and two attachments
time-sheet.ods
and payment-terms.pdf
to the generated invoice:
$ curl -v -X POST \
http://localhost:3000/api/invoice/transform-and-create/UBL \
-F mapping=@contrib/mappings/default-invoice.yaml \
-F data=@contrib/templates/1234567890-consulting/default-invoice.ods \
-F pdf=@invoice.pdf \
-F attachment=@time-sheet.ods \
-F description="Detailed description of hours spent." \
-F mimeType="application/vnd.oasis.opendocument.spreadsheet" \
-F attachment=@payment-terms.pdf \
-F description="Our payment terms" \
-F mimeType="application/pdf"
The invoice document data structure is documented here: https://docs.peppol.eu/poacc/billing/3.0/syntax/ubl-invoice/
If you prefer to have it all on one page, look here: https://docs.peppol.eu/poacc/billing/3.0/syntax/ubl-invoice/tree/
A gentler introduction can be found here: https://docs.peppol.eu/poacc/billing/3.0/bis/
Please see the mapping documentation!
Amounts have to be numbers >= 0 with at most two decimal places. The following JSON schema should work for this:
{
"type": "number",
"multipleOf": 0.01
}
This is even documented in the JSON Schema documentation. Unfortunately, this does not work with the JavaScript implementation, see https://github.com/ajv-validator/ajv/issues/652.
There are workarounds for this limitation of Ajv but I want to avoid people naïvely validating against the schema with Ajv without applying the necessary workaround. It looks simpler to require all amounts to be formatted beforehand by the software that generates the input data.
The problem for percentages is the same only that percentages can have up to four decimal digits.
For other numerical types, like quantities, we could use numbers but for consistency we use strings throughout the schema.
See SheetJS GitHub issue #1569. You can probably ignore this warning, unless you run into a problem with number formats.
You will often see references to business terms in validation error messages. You can look up to which elements they belong in the documentation file BusinessTerms.md.
Make sure that only the sheet that contains the printable invoice data has
a print range defined. You can check that with the menu entry
Format -> Print Ranges -> Edit
. For all other sheets, all three options
have to be set to None
.
Please report bugs at https://github.com/gflohr/e-invoice-eu/issues.
The Factur-X resp. ZUGFeRD standard requires PDF/A compliance for the PDF that the invoice is wrapped in. Please search the internet if you do not know what PDF/A means.
This library creates PDFs solely with pdf-lib
and does some pretty complicated transformations on the PDF to achieve PDF/A
compliance. This is not battle tested and may fail.
If you encounter a PDF that does not meet the PDF/A requirements, please open an issue and attach an anonymized version of the PDF. What you can do in the meantime:
gs -dVERBOSE -dPDFA=3 -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=OUTPUT_FILE.pdf PDFA_def.ps INPUT_FILE.pdf
libreoffice --headless "-env:UserInstallation=file:///tmp/LibreOffice_Conversion_${USER}" --convert-to 'pdf:writer_pdf_Export:{"SelectPdfVersion":{"type":"long","value":"3"}}' SOURCE_FILE.ods
On Un*x systems, libreoffice
should be in your $PATH
. On MacOS, you will
find it under /Applications/LibreOffice.app/Contents/MacOS/soffice
. On
MS Windows, it is probably somewhere like C:\\Program Files\\LibreOffice\\libreoffice.exe
(corrections are welcome).
All invoice formats that are variants of UBL or CII should be relatively easy to support. Please file an issue if you need an invoice format that is currently not supported.
Credit notes and other documents like orders are currently not supported and support for it will require more effort.
EDI is also not supported. If you know of a tool that is able to convert UBL or CII to EDI, please let us know!
This is free software available under the terms of the WTFPL.