EN 16931 e-invoices (khata-en16931)¶
crates/khata-en16931 is a pure, country-neutral crate for the European
standard on electronic invoicing, EN 16931: a semantic invoice model, its
core business rules as checks, and writers for the standard's two
syntaxes. A country pack maps its books' invoice to the model; Germany
does so in khata_de::xrechnung (see docs/germany-vat.md).
Sources: the CEN/TC 434 validation artefacts,
github.com/ConnectingEurope/eInvoicing-EN16931 (EUPL 1.2): Schematron
ubl/schematron/abstract/EN16931-model.sch (rule texts),
ubl/schematron/UBL/EN16931-UBL-model.sch (tests and tolerances), the
code lists, the D16B CII subset schemas and example invoices; the OASIS
UBL 2.1 schemas (docs.oasis-open.org/ubl/os-UBL-2.1); KoSIT's XRechnung
Schematron v2.6.0 and docs.peppol.eu for the CIUS identifiers
(docs/research/germany-compliance.md §9 to §11). The EN 16931-1 text
itself is a paid CEN standard and was not read.
Use¶
let mut inv = Invoice::new("RE-1", date, TypeCode::Commercial, "EUR");
inv.seller = …; inv.buyer = …; inv.lines = …; // BT/BG fields
inv.finalise(); // BG-23 and BG-22
let problems = validate_for(&inv, Specification::XRechnung3);
let xml = ubl::write(&inv, Specification::XRechnung3); // or cii::write
The writers do not validate: write only an invoice whose fatal violations
(rules::fatal) are empty, or show them to the user.
Model (model.rs)¶
| Group / term | Field |
|---|---|
| BT-1, 2, 3, 5 | number, issue_date, type_code (380, 381, 384, 389, 326), currency |
| BT-7, 9, 10, 13, 20, BG-1/BT-22 | tax_point_date, due_date, buyer_reference, order_reference, payment_terms, notes |
| BG-3 (BT-25, 26) | preceding |
| BG-4 Seller (BT-27, 28, 30, 31, 32, 34, BG-5, BG-6) | seller: Party (name, trading name, legal id, VAT id, tax registration, electronic address, address, contact) |
| BG-7 Buyer (BT-44 ff.) | buyer: Party |
| BT-72, 80, BG-14 | delivery_date, deliver_to_country, period |
| BG-16, BG-17 (BT-81 to 86) | payment: PaymentInstructions (means code, text, remittance, IBAN/name/BIC) |
| BG-20, BG-21 | allowances_charges (amount, base, percent, category, rate, reason, reason code) |
| BG-22 (BT-106 to 115) | totals |
| BG-23 (BT-116 to 121) | vat_breakdown |
| BG-25 (BT-126 to 131, 146, 149, 151 to 155) | lines |
VAT categories (BT-118/151): S, Z, E, AE, K, G, O, L, M, with their rule
names. units::rec20 maps free-text unit symbols to UN/ECE Rec 20 codes
(BT-130), all from the artefacts' code list.
Not modelled: payee (BG-10), tax representative (BG-11), deliver-to address (BG-15), line allowances/charges (BG-27/28), item attributes and classifications, attachments (BG-24), card and direct-debit payment (BG-18/19), accounting-currency VAT (BT-6/111), Skonto.
Invoice::finalise works out the breakdown (one per category, and per
rate for S/L/M; taxable = lines − allowances + charges; tax = taxable ×
rate ÷ 100 rounded to two decimals, half away from zero) and the totals,
keeping exemption reasons given beforehand
(VatBreakdown::exemption) and adding the CEF VATEX defaults for AE
(VATEX-EU-AE), K (VATEX-EU-IC), G (VATEX-EU-G) and O
(VATEX-EU-O) [PRIMARY: code list].
Rules (rules.rs)¶
validate checks the core rules; validate_for(inv, spec) adds the
CIUS's. Each Violation has the rule id, a message and warning (the
rule's flag is not "fatal").
- Presence: BR-02, 05 to 11, 16, 21, 23, 25, 27, 29, 33/BR-CO-21, 38/BR-CO-22, 48, 49, 50, 61. (BR-01 is the writers'; the rest hold by construction.)
- BR-CO-09 (VAT id prefix shape), BR-CO-10 to 18, BR-CO-19, BR-CO-26.
- BR-DEC-*: at most two decimals on amounts.
- Category rules -01, -02, -05/-06, -08, -09, -10 for S, Z, E, AE, K
(
BR-IC-*), G and O, plus BR-O-11 to 13 and BR-IC-11/12; for L and M only the rate sign. - BR-CO-17 and BR-S-09 accept a tax amount strictly within ±1 of
taxable × rate, as the artefacts test it (the rule text says "rounded
to two decimals";
finaliseproduces the exact value). - XRechnung 3.0 (
rules::xrechnung), flags from the KoSIT Schematron v2.6.0 [PRIMARY]: BR-DE-1 to 9, 14, 15, 16, 23-a/b (fatal); BR-DE-17, 19 (IBAN check), 26, 27, 28 (warnings). Two more warnings under KhataOS ids,KHATA-XR-BT-34/-BT-49: XRechnung 3.0 is reported to require the electronic addresses, but no rule was found [UNCERTAIN]. Not checked: BR-DE-10/11, 18, 22, 24, 25, 30, 31 (groups not modelled).
Not checked: the code lists (BR-CL-*), XSD validity. Run KoSIT's
validator (itplr-kosit/validator-configuration-xrechnung) or the
Peppol validator on real output.
Syntaxes¶
Specification sets BT-24 (and BT-23):
| Specification | CustomizationID (BT-24) | ProfileID (BT-23) |
|---|---|---|
En16931 |
urn:cen.eu:en16931:2017 |
— |
XRechnung3 |
urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0 [PRIMARY] |
urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 (optional in XRechnung [UNCERTAIN]) |
PeppolBis3 |
urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 [PRIMARY] |
urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 [PRIMARY] |
- UBL 2.1 (
ubl.rs):Invoice, orCreditNotefor type 381, in the UBL 2.1 schema order (checked against the OASIS XSDs). BT-32 is a secondPartyTaxSchemewith schemeFC; BT-9 on a CreditNote goes inPaymentMeans/PaymentDueDate. - UN/CEFACT CII D16B (
cii.rs):rsm:CrossIndustryInvoicein the D16B subset order (checked against the artefacts' XSD); BT-31/32 asSpecifiedTaxRegistrationwithVA/FC; dates in format 102; BT-84 asIBANID(orProprietaryID). The same XML is what a ZUGFeRD / Factur-X PDF embeds (profile EN 16931 or XRECHNUNG). - Category O writes no rate, except on the breakdown of an XRechnung (BR-DE-14 asks for BT-119 everywhere; the artefacts' XRechnung example writes 0).
Amounts are written with two decimals, prices, quantities and rates without trailing zeros. Text is escaped; XML-invalid control characters are dropped.
Tests¶
cargo test -p khata-en16931: breakdown and totals; each totals rule
(BR-CO-10 to 16, BR-DEC); the tolerance of BR-CO-17/BR-S-09; S, Z, E, AE,
K, G and O rules; presence and payment rules; XRechnung rules; golden
XML snippets for both syntaxes (Invoice and CreditNote, allowances,
exemptions, O without rate), all parsed as well-formed XML.
Peppol PINT (pint.rs)¶
Peppol PINT billing (the international core, urn:peppol:pint:billing-1)
reuses the EN 16931 terms but not the EU VAT rules: each jurisdiction has
its own tax category codes and rules. pint::PintInvoice wraps an
Invoice (parties, lines, payment, totals) and carries a PINT tax
category per line and per document allowance/charge (LineTax);
finalise builds the breakdown from those, validate checks the shared
PINT rules (ibr-*) and the jurisdiction's, and write writes UBL 2.1. Two
specialisations:
| PINT SG Billing 1.4.1 | PINT AE Billing 1.0.4 | |
|---|---|---|
| BT-24 | urn:peppol:pint:billing-1@sg-1 |
urn:peppol:pint:billing-1@ae-1 |
| BT-23 | urn:peppol:bis:billing |
urn:peppol:bis:billing |
| Categories | SR, SRCA-S, SRCA-C, SRRC, SROVR-RS, SROVR-LVG, SRLVG, ZR, ES33, ESN33, DS, OS, NA, NG (tax scheme GST) |
S, Z, E, O, AE (tax scheme VAT; N not modelled) |
| Endpoint | 0195 + SGUEN<UEN> |
0235 + TIN |
| Extra | cbc:UUID, single Note |
cbc:ProfileExecutionID, cbc:UUID, gross price, ItemPriceExtension, legal id type, credit note reason |
Sources: docs.peppol.eu PINT SG and PINT AE pages, Schematron, code lists
and examples [PRIMARY]; see docs/peppol.md and
docs/research/einvoicing-peppol.md. The
golden samples validate against the UBL 2.1 XSDs; the official Schematron
(XSLT 2.0) was not run.
Factur-X / ZUGFeRD PDF (facturx.rs)¶
facturx::pdf(inv, cii_xml, opts) writes a PDF/A-3b file (by hand, no PDF
crate) that shows the invoice as monospaced text and embeds the CII XML
(cii::write(inv, Specification::En16931), guideline
urn:cen.eu:en16931:2017) as factur-x.xml with /AFRelationship
/Alternative, the Factur-X XMP properties (fx:ConformanceLevel EN
16931) and their PDF/A extension schema, an sRGB output intent and an
embedded TrueType font (Courier Prime, SIL OFL 1.1, in assets/).
facturx::CONFORMANCE_GAPS lists what is not verified (no veraPDF or
Factur-X validator run, level B only, WinAnsi text only, D16B vs D22B…).
See docs/peppol.md.
cargo test -p khata-en16931 also covers both PINT jurisdictions (rules,
golden UBL snippets for Invoice and CreditNote, NG, exports, allowances) and
the Factur-X PDF (structure, xref offsets, XMP, embedded XML, widths,
pagination).