Create and import e-invoices with ERPNext.
In particular, this app supports reading and writing electronic invoices according to the UN/CEFACT Cross-Industry-Invoice (CII) standard in the following profiles:
- BASIC
- EN 16931
- EXTENDED
- XRECHNUNG
All profiles except for "XRECHNUNG" can be embedded in a PDF file, known as ZUGFeRD or Factur-X.
This app cannot read or write UBL invoices. It also does not provide any special way of sending or receiving e-invoices (e.g. Peppol). Instead, it focuses on the conversion between ERPNext's internal data model and the XML format of the above standards.
You can install this app using the bench CLI:
cd $PATH_TO_YOUR_BENCH
bench get-app https://github.com/alyf-de/eu_einvoice --branch $MAJOR_VERSION
bench install-app eu_einvoice
Please use a branch (MAJOR_VERSION
) that matches the major version of ERPNext you are using. For example, version-14
or version-15
. If you are a developer contributing new features, you'll want to use the develop
branch instead.
E-invoices rely on common codes that describe the content of the invoice. E.g. "C62" is used for the UOM "One" and "ZZZ" is used for a mutually agreed mode of payment.
Common codes are part of a code list. You'll need to import the code lists and map the codes you need to the corresponding ERPNext entities. Please use the "Import Genericode" button in Code List and paste the URL linked below.
Code List | Mapped DocType | Default Value |
---|---|---|
UNTDID 4461 Payment means code | Payment Terms Template, Mode of Payment | ZZZ |
Codes for Units of Measure Used in International Trade | UOM | C62 |
Codes for Passengers, Types of Cargo, Packages and Packaging Materials (optional) | UOM | C62 |
Codes for Duty Tax and Fee Categories | Item Tax Template, Account, Tax Category, Sales Taxes and Charges Template | S |
VAT exemption reason code list | Item Tax Template, Account, Tax Category, Sales Taxes and Charges Template | vatex-eu-ae |
For example, let's say your standard Payment Terms Template is "Bank Transfer, 30 days". You'll need to find the suitable Common Code for bank transfers within the Code List "UNTDID.4461". In this case, the code is "58". Then you add a row to the Applies To table, select "Payment Terms Template" as the Link Document Type and "Bank Transfer, 30 days" as the Link Name. If you now create an Invoice with this Payment Terms Template, the eInvoice will contain the code "58" for the payment means, signalling that the payment should done via bank transfer.
The retrieval of codes goes from the most specific to the most general. E.g. for determining the VAT type of a line item, we first look for a code using the specific item's Item Tax Template and Income Account, then fall back to the code for the invoice's Tax Category or Sales Taxes and Charges Template.
If you work with government customers or similar large organizations, you might need to specify their Buyer Reference in the eInvoice. This is done by setting the Buyer Reference field in the Sales Invoice. You can already fill this field in the Customer master data or the Sales Order.
During validation of the Sales Invoice, the potential eInvoice is created and validated against the schematron rules for the selected E Invoice Profile, so that you can see any potential problems before submitting it.
To download the XML file (XRechnung), open a Sales Invoice and click on "..." > "Download eInvoice".
When you open the print preview of the Sales Invoice and click on "PDF", the generated PDF file will have the e-invoice XML embedded. An exception is the E Invoice Profile "XRECHNUNG", which is intended to be a plain XML file. In this case, the PDF will not have the XML embedded.
Tip
You can test both XML and PDF+XML files by re-importing them, using the E Invoice Import DocType.
The following fields of the Sales Invoice are currently considered for the eInvoice:
- Invoice type (credit note, corrected invoice, commercial invoice)
- Invoice number
- Invoice date
- Due date
- From date
- To date
- Language
- Currency
- Company
- Phone No
- Fax
- Company Name
- Company Address
- Address Line 1
- Address Line 2
- Postcode
- City
- Country
- Company Contact Person
- Full Name
- Email Address (takes precedence over Company > Email)
- Phone (takes precedence over Company > Phone No)
- Department
- Company Tax ID
- Customer Name
- Buyer Reference (fetched from Sales Order or Customer)
- Customer Address
- Address Line 1
- Address Line 2
- Postcode
- City
- Country
- Contact Email
- Contact Mobile (takes precedence over Contact Person > Phone)
- Contact Person
- Full Name
- Phone
- Department
- Customer's Purchase Order
- Customer's Purchase Order Date
- Customer's Tax ID
- Items:
- Item Name
- Description
- Company's Item Code
- Customer's Item Code
- Delivery Note number and date
- Quantity + Unit
- Rate
- Net Amount
- Amount
- Terms and Conditions Details (converted to markdown)
- Incoterm and named place
- Payment Schedule
- Description
- Due date
- Amount
- Discount Type (must be "Percentage")
- Discount
- Discount Date
- Sales Taxs and Charges
- The Charge Type "Actual" is used as logistics or service charges.
- For Charge Type "On Net Total", the taxable amount is calculated as
tax_amount / rate * 100
, if the rate is available in the tax row or in the corresponding Account [1]. - The Charge Type "On Item Quantity" is not supported.
- Total
- Discount Amount
- Net Total
- Total Taxes and Charges
- Grand Total
- Total Advance
- Outstanding Amount
[1] The correct taxable amount is only available starting from ERPNext v16. For earlier versions we currently have to approximate it, which comes with a small error margin.
To import a new eInvoice, create a new E Invoice Import and upload the XML or PDF file.
We extract the E-Invoice Profile and validate the XML against the corresponding schematron rules.
A correct eInvoice will look like this:
A problematic eInvoice will look like this. You can see the validation errors in the Validation Details section:
It is still possible to import an invoice, even if there are formal validation errors.
Taxes are mapped to "Actual" charges in the Purchase Invoice, so that ERPNext does not try to recalculate them.
You can find XML files for testing in the following repositories:
This app provides hooks to add custom logic to the eInvoice creation process:
-
before_einvoice_generation
Called right before the eInvoice is generated. The hook function receives the Sales Invoice as an argument and can modify it.
-
after_einvoice_generation
Called right after the eInvoice is generated. The hook function receives the Sales Invoice and the generated eInvoice as arguments.
For example, your myapp/hooks.py
could look like this:
doc_events = {
"Sales Invoice": {
"before_einvoice_generation": "myapp.einvoice.before_einvoice_generation",
"after_einvoice_generation": "myapp.einvoice.after_einvoice_generation",
}
}
And your myapp/einvoice.py
like this:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from drafthorse.models.document import Document
from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice
def before_einvoice_generation(doc: "SalesInvoice", event: str):
"""Modify the Sales Invoice object before generating the eInvoice."""
doc.customer_name = "Special Customer Name"
def after_einvoice_generation(doc: "SalesInvoice", event: str, einvoice: "Document"):
"""Modify the generated eInvoice after it was created."""
einvoice.trade.agreement.buyer.name = doc.customer_name
Warning
These methods are also triggered during the validate
event of the Sales Invoice. In this case, if you change the Sales Invoice object, these changes will be saved to the database.
You can upload an XML invoice file to https://www.itb.ec.europa.eu/invoice/upload and validate it as "CII Invoice CML".
This app uses pre-commit
for code formatting and linting. Please install pre-commit and enable it for this repository:
cd apps/eu_einvoice
pre-commit install
Pre-commit is configured to use the following tools for checking and formatting your code:
- ruff
- eslint
- prettier
- pyupgrade
This app can use GitHub Actions for CI. The following workflows are configured:
- CI: Installs this app and runs unit tests on every push to
develop
branch. - Linters: Runs Frappe Semgrep Rules and pip-audit on every pull request.
-
drafthorse by Raphael Michel, released under the Apache License 2.0
Used to create and parse XML invoices.
-
factur-x by Alexis de Lattre, released unser a BSD License
Used to extract XML data from PDF files, and to create PDF files with embedded XML.
-
SaxonC by Saxonica
Used for XSL transformation (validate XML against schematron).
-
lxml by Infrae
Used for general XML parsing.
-
SchXslt by David Maus
Used to convert Schematron files to XSL.
Many thanks to the following companies for sponsoring the initial development of this app:
- aepfel+birnen IT GmbH
- axessio Hausverwaltung GmbH
- Burkhard Baumsteigtechnik GmbH & Co. KG
- DriveCon GmbH
- ibb testing gmbh
- itsdave GmbH
- iXGate UG
- Kautenburger IT GmbH
- MERECS Engineering GmbH
- voidsy GmbH
- … and many more
Note
We only list companies that have explicitly agreed to have their name published here. If you want to be listed here too, please send us a short note by email.
Copyright (C) 2024 ALYF GmbH
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.