Create and import PEPPOL-compliant e-documents with ERPNext.
This app provides a flexible framework for generating and parsing electronic documents, with full support for PEPPOL BIS Billing 3.0 using UBL 2.1 XML format.
- PEPPOL BIS Billing 3.0 Support: Full implementation of PEPPOL BIS Billing 3.0 specification
- UBL 2.1 XML Generation: Generate compliant UBL 2.1 XML for invoices and credit notes
- Multiple Document Types: Support for Invoice and CreditNote
- XML Validation: XSD schema validation and Schematron business rule validation
- HTML Preview: Visual preview of generated XML using XSLT transformations (auto-displayed on load)
- Entity Matching: Match incoming XML entities (supplier, items, PO) to ERPNext master data with manual fallback
- Code List Management: Automatic code list handling for PEPPOL standards
- Profile-Based Architecture: Extensible profile system for different e-document standards
- Import/Export: Import incoming PEPPOL invoices and export outgoing invoices
| Frappe/ERPNext | Branch | Python | Node.js |
|---|---|---|---|
| v15 | version-15 |
3.10 | 18 |
| v16 | develop |
3.14 | 24 |
cd $PATH_TO_YOUR_BENCH
# For Frappe/ERPNext v15
bench get-app https://github.com/prilk-consulting/edocument --branch version-15
# For Frappe/ERPNext v16 (develop)
bench get-app https://github.com/prilk-consulting/edocument
# Install on your site
bench --site your-site install-app edocumentThis app requires the following Python packages (automatically installed):
- saxonche (~=12.5.0): XSLT 3.0 processor for Schematron validation and HTML preview
- lxml (>=4.9.3,<6.0.0): XML parsing, XSD validation, and XSLT processing
These dependencies are specified in pyproject.toml and will be installed automatically when you install the app.
E-documents rely on common codes that describe the content of the document. 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 Duty Tax and Fee Categories | Item Tax Template, Account, Tax Category, Sales Taxes and Charges Template | S |
| Electronic Address Scheme | Company, Customer, Supplier | EM |
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 e-document will contain the code "58" for the payment means.
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.
For PEPPOL profiles, additional code lists are required. These can be imported using the "Import Genericode" button in Code List:
| Code List | Purpose |
|---|---|
| PEPPOL Payment Means Code | Payment methods for PEPPOL invoices |
| PEPPOL Unit of Measure Code | Units of measure for PEPPOL line items |
| PEPPOL Tax Category Code | Tax categories for PEPPOL invoices |
| PEPPOL Country Code | Country codes for addresses |
| PEPPOL Electronic Address Identifier Scheme | Electronic address schemes for PEPPOL participants |
These code lists are automatically set up when you install the app. You can verify and update mappings in the Code List doctype.
The PEPPOL code lists are sourced from the PEPPOL BIS Billing 3.0 repository and are included in the app's edocument/profiles/peppol/peppol-bis-invoice-3/structure/codelist/ folder.
The UBL 2.1 XSD schemas are sourced from the OASIS UBL 2.1 specification and are included in the app's edocument/profiles/peppol/UBL-2.1/xsd/ folder.
If you send your invoice via PEPPOL, you might need to specify your and your customer's electronic addresses. This is done by setting the Electronic Address Scheme and Electronic Address fields in the Company, Customer and Supplier master data.
Please make sure to import the Electronic Address Scheme code list first.
If not specified, email addresses are used as electronic addresses for outgoing invoices. For the Customer, we use the Contact Email or Buyer Address > Email ID. For the Company, we use the Seller Contact > Email ID or Company > Email.
If you want your e-document to contain bank details, you need to set up a Mode of Payment of type "Bank", link the company's corresponding Account and create a Bank Account for the same account with IBAN and BIC (SWIFT number).
Then, you can map a Common Code from Code List "UNTDID.4461", e.g. "Credit Transfer" (30) or "SEPA Credit Transfer" (58), to the Mode of Payment.
Please note that the e-document standard only supports one payment means per invoice, so you should not specify multiple Modes of Payment in the same invoice.
Most invoices use standard VAT rates (S) or zero-rated VAT (Z, automatically detected for 0% rates). For special cases:
-
VAT Exempt (E): Create a Tax Category (e.g., "VAT Exempt") and map it to code "E" in Common Code. Use this tax category on invoices with exempt items like books, education, or healthcare.
-
Out of Scope (O): Create a Tax Category (e.g., "Out of Scope") and map it to code "O" in Common Code. Use for non-business transactions or items not subject to VAT. When any invoice line uses "O", VAT identifiers are automatically omitted from the entire invoice per PEPPOL rules.
For item-specific tax treatment, map codes to Item, Item Tax Template or Account instead of Tax Category.
For sales to businesses in other EU countries with 0% VAT (intra-community supply):
-
Setup: Create a Tax Category (e.g., "Intra-Community") and map it to code "K" in Common Code.
-
Automatic Handling: When any invoice line uses category "K", the app automatically:
- Adds
TaxExemptionReasonCodewith valueVATEX-EU-IC - Adds
TaxExemptionReasonwith text "Intra-community supply" - Adds
Deliveryelement with:ActualDeliveryDate(uses delivery date or posting date)- Delivery country code (from shipping address or customer address)
- Adds
-
PEPPOL Rules Satisfied:
- BR-IC-10: Exemption reason code/text for IC supply
- BR-IC-11: Actual delivery date is required
- BR-IC-12: Delivery country code is required
Example: A Dutch company sells goods to a German company. Set the Tax Category to "Intra-Community" (mapped to "K"). The e-document will include 0% VAT with IC exemption reason and delivery details proving goods were delivered to Germany.
Configure EDocument settings in the Company master data:
- EDocument Profile: Default profile to use for this company
- Electronic Address Scheme: Scheme for the company's electronic address (e.g., GLN, EAS)
- Electronic Address: The company's electronic address identifier
Configure EDocument settings in the Customer master data:
- EDocument Profile: Default profile to use for this customer
- Electronic Address Scheme: Scheme for the customer's electronic address
- Electronic Address: The customer's electronic address identifier
Configure EDocument settings in the Supplier master data:
- EDocument Profile: Default profile to use for this supplier
- Electronic Address Scheme: Scheme for the supplier's electronic address
- Electronic Address: The supplier's electronic address identifier
The EDocument Profile defines the configuration for a specific e-document standard (e.g., PEPPOL). It includes:
Identifier Settings (used to detect the profile from XML):
- Identifier Namespace: XML namespace where the identifier element is found
- Identifier Element Name: Name of the XML element containing the profile identifier
- Identifier Value: The value that uniquely identifies this profile
Function Paths:
- Generator Path: Function that generates XML from ERPNext documents
- Parser Path: Function that parses XML into ERPNext documents
- Validator Path: Function that validates XML against schemas and business rules
- Preview Path: Function that converts XML to HTML preview using XSLT
- Detector Path: Function that auto-detects fields from incoming XML
- Matcher Path: Function that matches XML entities (supplier, items, PO) to ERPNext master data
Sales Invoice Settings:
- EDocument generation on Save: Automatically create EDocument when Sales Invoice is saved (draft)
- EDocument generation on Submit: Automatically create EDocument when Sales Invoice is submitted
- Ignore Validation Error for EDocument generation: Allow EDocument creation even if validation fails (shows warning instead of blocking)
The PEPPOL profile is automatically created when you install the app.
In the Sales Invoice, you can:
- Select an EDocument Profile (defaults from Customer if set)
- When the invoice is submitted, an EDocument record is automatically created (if profile is set)
- The EDocument can then be used to generate and validate the PEPPOL XML
Tip: Use the Customer Purchase Order field to set the buyer's reference number. This field is mapped to the BuyerReference element in the PEPPOL e-document, which is often required by customers for invoice processing.
For outgoing e-documents (generated from Sales Invoices):
- Set the Source Type (e.g., "Sales Invoice")
- Set the Source Document (the Sales Invoice name)
- Select the EDocument Profile (e.g., "PEPPOL")
- Click Generate XML to create the PEPPOL XML
- The XML is automatically validated
- The XML file is attached to the EDocument record
- Click Preview EDocument to view the formatted HTML preview
For incoming e-documents (imported XML files):
- Upload the XML file
- The app automatically detects the document type and profile
- The XML is validated against XSD and Schematron rules
- The preview is automatically displayed when opening the EDocument
- Click Match Document to match XML entities (supplier, items, PO) to ERPNext master data
- If entities are not auto-matched, a dialog allows manual selection
- Matched data is saved for use when creating the document
- Click Create Document to parse the XML and create a Purchase Invoice using matched entities
- Click Review and Create Document to review the parsed data before saving
When validation fails, the EDocument record shows:
- Status: "Validation Failed"
- Error: Detailed validation error messages
- Warnings: Any validation warnings (non-blocking)
Common validation errors include:
- XSD schema violations (element order, missing required fields)
- Schematron business rule violations (BR-CO-15, BR-CO-17, etc.)
- Missing required codes or invalid code values
For both incoming and outgoing e-documents with existing XML, you can preview the XML content as formatted HTML:
- Ensure the EDocument has XML attached (generate it first if needed using Generate XML)
- Click Preview EDocument to view the formatted HTML preview
- The preview displays the invoice/credit note in a human-readable format using XSLT transformations
- The HTML preview includes proper styling and formatting for easy reading
The preview functionality uses profile-specific XSLT stylesheets to transform the UBL XML into styled HTML, making it easy to verify the document content before sending or processing.
Note: The Preview button only appears when XML files are attached to the document. Use Generate XML first for outgoing documents.
Before using the app, you need to create an EDocument Profile that defines which profile to use (e.g., PEPPOL) and the generator/parser paths.
- Go to EDocument Profile doctype
- Create a new profile (e.g., "PEPPOL")
- Set the profile identifier values:
- Identifier Namespace:
urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2 - Identifier Element Name:
CustomizationID - Identifier Value:
urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
- Identifier Namespace:
- Set the function paths:
- Generator Path:
edocument.edocument.profiles.peppol.generator.generate_peppol_xml - Parser Path:
edocument.edocument.profiles.peppol.parser.parse_peppol_xml - Validator Path:
edocument.edocument.profiles.peppol.validator.validate_peppol_xml - Preview Path:
edocument.edocument.profiles.peppol.preview.preview_peppol_xml - Detector Path:
edocument.edocument.profiles.peppol.detector.detect_edocument_fields - Matcher Path:
edocument.edocument.profiles.peppol.matcher.match_peppol_xml
- Generator Path:
To create an outgoing e-document, you need to create an EDocument record:
- Go to EDocument doctype
- Create a new document
- Set the Source Type (e.g., "Sales Invoice")
- Set the Source Document (the Sales Invoice name)
- Select the EDocument Profile (e.g., "PEPPOL")
- Click Generate XML - this will create the PEPPOL XML and attach it to the document
- The XML is automatically validated against XSD and Schematron rules
- Click Preview EDocument - this will show an HTML preview of the generated XML
- Click Validate XML - this will validate the PEPPOL XML.
The following fields of the Sales Invoice are currently considered for the e-document:
- Invoice type (credit note, corrected invoice, commercial invoice)
- Invoice number
- Invoice date
- Due date (only for invoices, not credit notes)
- Currency
- Customer Purchase Order (used as BuyerReference in the e-document)
- Company information (name, address, tax ID, electronic address)
- Customer information (name, address, tax ID, electronic address)
- Items (name, description, quantity, rate, net amount, tax rate)
- Taxes (rate, amount, taxable amount)
- Payment means (bank account with IBAN and BIC)
- Payment terms
- Totals (line extension amount, tax exclusive amount, tax inclusive amount, payable amount)
- Document-level discounts and allowances
Credit notes are automatically detected when a Sales Invoice has is_return = 1. The app will:
- Use
CreditNoteas the root XML element (instead ofInvoice) - Use
CreditNoteTypeCodeinstead ofInvoiceTypeCode - Use
CreditNoteLineinstead ofInvoiceLine - Exclude
DueDate(credit notes don't have due dates) - Include
BillingReferenceto reference the original invoice - Use the CreditNote XSD schema for validation
To import an incoming e-document:
- Go to EDocument doctype
- Create a new document
- Upload the XML file
- The app will automatically:
- Detect the document type (Invoice, CreditNote, etc.)
- Detect the profile (PEPPOL)
- Validate the XML against XSD and Schematron rules
- Parse the XML and create a Purchase Invoice
The following fields are imported from the e-document:
- Invoice ID
- Issue Date
- Currency
- Seller (Supplier) information
- Buyer (Company) information
- Items (product name, description, quantity, rate, tax rate)
- Taxes (basis amount, rate, calculated amount)
- Payment terms
- Payment means (IBAN, BIC)
- Monetary totals
The app performs comprehensive validation of generated and imported XML:
- XML Syntax Validation: Ensures the XML is well-formed
- XSD Validation: Validates the XML against the UBL 2.1 XSD schema (Invoice or CreditNote)
- Schematron Validation: Validates business rules using PEPPOL Schematron files
Validation results are displayed in the EDocument record:
- Status: Validation Successful / Validation Failed / Matching Successful / Matching Failed
- Error: Any validation errors
- Warnings: Any validation warnings
- Matching Summary: Summary of entity matching results
For PEPPOL invoices (UBL 2.1), you can use the PEPPOL Validation Service or your PEPPOL service provider's validation tools.
The app follows a modular, profile-based architecture:
generator.py: Converts ERPNext invoice data to UBL 2.1 XMLparser.py: Parses UBL 2.1 XML and creates ERPNext documentsvalidator.py: XSD and Schematron validationpreview.py: XSLT-based HTML preview generationdetector.py: Auto-detects EDocument fields from incoming XMLmatcher.py: Matches XML entities to ERPNext master dataprofiles/: Profile-specific implementations (PEPPOL, etc.)
The app uses a profile-based system that allows different e-document standards to be implemented:
- PEPPOL Profile: Full PEPPOL BIS Billing 3.0 implementation
- Extensible: Easy to add new profiles (e.g., country-specific CIUS)
Each profile defines:
- Generator function (creates XML from ERPNext data)
- Parser function (creates ERPNext data from XML)
- Validator function (validates XML)
- Preview function (converts XML to HTML using XSLT)
- Detector function (auto-detects fields from incoming XML)
- Matcher function (matches XML entities to ERPNext master data)
- Profile identifier (for automatic detection)
For incoming e-documents, the app automatically detects and populates fields using the profile's detector:
- Company: Detected from buyer's EndpointID matching Company's electronic address
- Country: Detected from seller's postal address country code
- Target Document Type: Detected from XML root element (Invoice → Purchase Invoice, CreditNote → Purchase Invoice)
For incoming e-documents, the app matches XML entities to ERPNext master data using the profile's matcher:
- Supplier: Auto-matched by name, tax ID, or electronic address
- Items: Auto-matched by buyer item ID or seller product ID via Item Supplier table
- Purchase Order: Auto-matched by OrderReference or BuyerReference
When auto-matching fails, users can manually select the correct entities via a matching dialog. The matched data is stored in the EDocument and used when creating the target document.
This app uses pre-commit for code formatting and linting. Please install pre-commit and enable it for this repository:
cd apps/edocument
pre-commit installPre-commit is configured to use the following tools for checking and formatting your code:
- ruff
- eslint
- prettier
- pyupgrade
Copyright (C) 2025 Prilk Consulting BV
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/.








