Durchsuchbare Dokumentation aufrufen | Zurück zur Dokumentationsübersicht
Navigation: Dokumentationen agorum core > agorum core Module und Plugins > Dokument | E-Rechnung
Hinweis: Diese Dokumentation bezieht sich auf die aktuellste Version des Plugins Dokument | E-Rechnung. Aktualisieren Sie das hier beschriebene Plugin, um die Dokumentation verwenden zu können.
Mit Dokument | E-Rechnung erstellen Sie ausgehende E-Rechnungen in den Formaten XRechnung (UBL oder CII), ZUGFeRD und Peppol BIS Billing 3.0. Grundlage sind immer die normalisierten Daten für die E-Rechnung: ein JSON-Objekt mit Schlüsseln wie agorum_accounting_document_number, das unabhängig vom Zielformat ist. Diese Seite beschreibt zwei Ausgangslagen:
Welches Format und welches Profil Sie wählen sollten, beschreibt undefined>E-Rechnungsformate, Versionen und Profile.
Der Workflow-Knoten E-Rechnung aus normalisierten Daten erstellen führt die Schritte 2, 4 und 5 automatisch aus: Er prüft die Pflichtfelder, erzeugt das XML, validiert es und erstellt die Rechnung nur, wenn die Prüfung erfolgreich war. Ist sie nicht erfolgreich, bricht der Knoten mit einem Fehler ab, der den Prüfbericht nennt.
Für die meisten Einsatzfälle ist ein Workflow der einfachste Weg: Sie konfigurieren die Knoten, statt Code zu schreiben, und der Knoten E-Rechnung aus normalisierten Daten erstellen übernimmt Pflichtfeldprüfung, Validierung und Erstellung in einem Schritt. Die Skriptbeispiele weiter unten richten sich an Entwickler, die die Schritte selbst steuern wollen.
Die folgenden Abschnitte beschreiben, was bei den Daten zu beachten ist. Sie gelten für Workflow und Skript gleichermaßen.
Typische Quellen sind ein Export aus dem ERP-System, die Metadaten an einem Rechnungsdokument in agorum core (Präfix agorum_accounting_document_) oder Daten, die docform aus einer PDF-Rechnung erkannt hat. In allen Fällen gehen Sie so vor:
Ordnen Sie jedes Feld Ihrer Quelle dem passenden normalisierten Feld zu. Die BT-Nummern in der Tabelle der normalisierten Daten helfen beim Abgleich mit der Feldliste Ihres Vorsystems. Beachten Sie dabei:
let objects = require('common/objects');
let eInvoice = require('/agorum/roi/customers/agorum.electronic.invoicing/js/lib/e-invoice');
let data = JSON.parse(objects.find('/agorum/roi/customers/agorum.electronic.invoicing/test/data/completeDataStructure.json').contentString);
let missing = eInvoice.checkRequiredFields(data, 'xrechnung_ubl');
// [] = alle Pflichtfelder vorhanden
// sonst z. B. [ { key: 'net_amount', label: 'net_amount - Wert auf Positions-Ebene fehlt' } ]
missing;
Die Funktion prüft, ob die für das Format erforderlichen Felder vorhanden sind. Für CII-Formate (xrechnung_cii, zugferd_cii) sind auf Rechnungsebene zusätzlich Fälligkeitsdatum, BIC sowie die elektronischen Adressen von Verkäufer und Käufer Pflicht; bei UBL verlangt die Vorprüfung dagegen in den Positionen zusätzlich net_amount. Die vollständige Liste finden Sie im Vergleich der Pflichtfelder in den E-Rechnungsformaten.
Hinweis: checkRequiredFields prüft nur, ob ein Feld vorhanden ist, nicht ob sein Inhalt plausibel ist. Bei den Positionen wird nur die erste Position geprüft. Die vollständige inhaltliche Prüfung übernimmt der KoSIT-Validator in Schritt 4.
Folgende Angaben fehlen in Exporten aus Vorsystemen besonders häufig:
| Angabe | Feld | Woher |
|---|---|---|
| Käuferreferenz / Leitweg-ID (BT-10) | agorum_accounting_document_buyer_reference_number | Vom Empfänger mitgeteilt; bei öffentlichen Auftraggebern die Leitweg-ID |
| Elektronische Adresse Verkäufer / Käufer (BT-34, BT-49) | agorum_accounting_document_supplier_endpoint_id, agorum_accounting_document_customer_endpoint_id | Eigene Stammdaten bzw. Kundenstamm. Im CII-/ZUGFeRD-Format steuern agorum_accounting_document_supplier_endpoint_scheme_id bzw. agorum_accounting_document_customer_endpoint_scheme_id das Schema (etwa 0204 für die Leitweg-ID, 9930 für die USt-IdNr.); ohne Angabe und im UBL-Format wird EM (E-Mail) geschrieben. |
| Kontakt des Verkäufers (BT-41 bis BT-43) | agorum_accounting_document_supplier_contact_name, agorum_accounting_document_supplier_phone, agorum_accounting_document_supplier_mail | Eigene Stammdaten, etwa als Konstante im Workflow |
| Bankverbindung (BT-84, BT-86) | agorum_accounting_document_payment_iban (BT-84), agorum_accounting_document_supplier_bic (BT-86); mehrere Bankverbindungen in agorum_accounting_document_payment_means | Eigene Stammdaten |
| Fälligkeit (BT-9) | agorum_accounting_document_due_date (bei CII Pflicht für die Vorprüfung, in UBL BT-9). Bei CII/ZUGFeRD hat ab Version 1.1.0 agorum_accounting_document_payment_due_date Vorrang, wenn es gesetzt ist. | Aus dem Zahlungsziel berechnen |
| Steuerkategorie je Position (BT-151) | tax_category in der Positionsliste, etwa S, AE, K, Z, E | Aus dem Steuerschlüssel des Vorsystems ableiten |
| Einheit (BT-130) | unit in der Positionsliste, etwa C62, HUR, DAY | Einheiten des Vorsystems auf UN/ECE-Codes abbilden |
Feste Angaben wie die eigenen Unternehmensdaten ergänzen Sie am einfachsten zentral im Workflow oder Skript, bevor Sie die Rechnung erzeugen. Angaben, die je Rechnung verschieden sind, etwa die Leitweg-ID, können Sie in einem Benutzerformular erfassen lassen, wenn sie im Vorsystem fehlen.
let xml = eInvoice.createInvoiceRaw({
data: data,
format: 'zugferd_cii',
profile: 'en16931',
});
let result = eInvoice.validate(xml, { createHtmlReport: true });
// result.valid: true/false, result.validation: Liste der Meldungen, result.htmlReport: Prüfbericht
result;
Werten Sie bei ungültigem Ergebnis die Meldungen in result.validation aus. Jede Meldung enthält die Regel (etwa [BR-DE-15]), den Schweregrad und die Fundstelle. Korrigieren Sie die Daten und wiederholen Sie die Prüfung.
XRechnung und Peppol entstehen als neue XML-Datei im Arbeitsordner des Plugins (/agorum/roi/workspace/agorum.electronic.invoicing/work/<Jahr>/<Monat>/<Tag>/) mit einer UUID als Namen. Verschieben oder kopieren Sie sie an ihren Zielort und benennen Sie sie sprechend, etwa nach der Rechnungsnummer:
let invoice = eInvoice.createInvoice({
data: data,
format: 'xrechnung_ubl',
});
let target = objects.find('home:MyFiles');
let copy = objects.copy(invoice, target);
copy.name = 'XRechnung ' + data.agorum_accounting_document_number + '.xml';
ZUGFeRD braucht ein PDF als Träger, in das die XML eingebettet wird. Das ist normalerweise die Rechnung, die Ihr Vorsystem als PDF erzeugt hat:
let pdf = objects.find('/Pfad/zur/Rechnung-4711.pdf');
let carrier = objects.copy(pdf, pdf.firstParent);
let invoice = eInvoice.createInvoice({
data: data,
format: 'zugferd_cii',
profile: 'en16931',
attachments: [carrier],
});
Achtung: Bei ZUGFeRD wird das übergebene PDF-Objekt selbst in ein PDF/A-3 mit eingebetteter XML umgewandelt und zurückgegeben. Arbeiten Sie deshalb wie im Beispiel mit einer Kopie, wenn das Original-PDF unverändert bleiben soll. Ist ein PDF/A-Konverter eingerichtet, wird ein PDF, das noch nicht PDF/A-3b ist, vorher konvertiert.
Achtung: PDF-Inhalt und eingebettete XML müssen inhaltlich übereinstimmen. Bei Abweichungen gilt rechtlich die XML. Erzeugen Sie die Daten und das PDF deshalb aus derselben Quelle.
Prüfen Sie das fertige Dokument mit validateInvoice(invoice, { createHtmlReport: true }) und legen Sie Rechnung und Prüfbericht gemeinsam ab. Den Versand richten Sie im Workflow ein, etwa per E-Mail, über ein Rechnungsportal des Empfängers oder über einen Peppol-Zugangspunkt. Dokument | E-Rechnung selbst versendet keine Rechnungen.
Liegen keine Rechnungsdaten vor, erfassen Sie sie direkt in der normalisierten Struktur. Dokument | E-Rechnung bringt dafür keine eigene Eingabemaske mit. Sie haben folgende Möglichkeiten:
Der folgende Datensatz ergibt mit Dokument | E-Rechnung 1.1.1 gültige Rechnungen in den Formaten xrechnung_ubl, xrechnung_cii und zugferd_cii (Profil en16931). Zwei Positionen, ein Steuersatz von 19 %, alle Summen stimmen. Sie können ihn in der Skript-Konsole ausprobieren (Hauptmenü Development > Skript-Konsole).
let objects = require('common/objects');
let eInvoice = require('/agorum/roi/customers/agorum.electronic.invoicing/js/lib/e-invoice');
let P = 'agorum_accounting_document_';
let data = {};
let set = (key, value) => data[P + key] = value;
// Rechnungskopf
set('number', 'RE-2026-001');
set('date', '2026-10-15T00:00:00.000Z');
set('due_date', '2026-11-14T00:00:00.000Z');
set('type_code', '380');
set('currency', 'EUR');
set('buyer_reference_number', '04011000-12345-34');
// Verkäufer
set('supplier_name', 'Musterlieferant GmbH');
set('supplier_street', 'Lieferweg 1');
set('supplier_zip', '70173');
set('supplier_city', 'Stuttgart');
set('supplier_country', 'DE');
set('supplier_vat_id', 'DE123456789');
set('supplier_contact_name', 'Erika Muster');
set('supplier_phone', '+49 711 123456');
set('supplier_mail', 'rechnung@lieferant.example');
set('supplier_endpoint_id', 'rechnung@lieferant.example');
set('supplier_bic', 'COBADEFFXXX');
// Käufer
set('customer_name', 'Beispielkunde AG');
set('customer_street', 'Kundenstrasse 5');
set('customer_zip', '10115');
set('customer_city', 'Berlin');
set('customer_country', 'DE');
set('customer_endpoint_id', 'eingang@kunde.example');
// Zahlung
set('payment_method', '58');
set('payment_iban', 'DE02120300000000202051');
set('payment_reference_id', 'RE-2026-001');
// Steuer und Summen (werden nicht berechnet, sondern übernommen)
set('tax_id_1', 'S');
set('tax_schema_id_1', 'VAT');
set('tax_rate_1', 19);
set('total_tax_rate_1', 19);
set('total_net_amount_1', 1100);
set('total_tax_amount_1', 209);
set('tax_total_amount', 209);
set('total_net_amount', 1100);
set('total_discountable_amount', 1100);
set('tax_basis_total_amount', 1100);
set('total_discount_amount', 0);
set('total_add_amount', 0);
set('total_gross_amount', 1309);
set('due_payable_amount', 1309);
// Positionen
set('item_list', [
{ number: '1', description: 'Beratung', quantity: 10, unit: 'HUR', net_price: 100,
net_amount: 1000, line_total_amount: 1000, tax_type: 'VAT', tax_category: 'S', tax_rate: 19, invoice_currency: 'EUR' },
{ number: '2', description: 'Schulungsunterlagen', quantity: 2, unit: 'C62', net_price: 50,
net_amount: 100, line_total_amount: 100, tax_type: 'VAT', tax_category: 'S', tax_rate: 19, invoice_currency: 'EUR' }
]);
let xml = eInvoice.createInvoiceRaw({ data: data, format: 'xrechnung_ubl' });
eInvoice.validate(xml); // { valid: true, validation: [ ] }
Für eine gültige Rechnung brauchen Sie mindestens:
Für ZUGFeRD brauchen Sie ein PDF. Liegt keines vor, erzeugen Sie es aus denselben Daten mit createView und einer Dokumentvorlage und übergeben es anschließend an createInvoice:
let outputDoc = objects.create('file', {
name: 'Rechnung-' + data.agorum_accounting_document_number + '.pdf',
target: objects.find('home:MyFiles'),
});
eInvoice.createView({
data: data,
template: {
outputDoc: outputDoc,
templateDoc: '/agorum/roi/customers/agorum.electronic.invoicing/template/Invoice_Template_Complete.docx',
createPdf: true,
},
});
let invoice = eInvoice.createInvoice({
data: data,
format: 'zugferd_cii',
profile: 'en16931',
attachments: [outputDoc],
});
Der Beispielworkflow agorum.electronic.invoicing.demo_complete zeigt denselben Ablauf als Workflow, siehe Beispielworkflows und Beispieldokumente verwenden.
Wenn Sie für die Neuerfassung ein Formular einrichten, beachten Sie folgende Punkte:
agorum_accounting_document_type_code): Auswahlliste mit den häufigsten Werten 380, 381, 384, 389. Bei 381 und 384 blenden Sie die Bezugsrechnung (agorum_accounting_document_billing_reference) als Pflichtfeld ein.agorum_accounting_document_currency, vorbelegt mit EUR) und Käuferreferenz bzw. Leitweg-ID (agorum_accounting_document_buyer_reference_number, von der Vorprüfung für alle Formate verlangt).unit), Nettopreis, Positionsbetrag (line_total_amount und für UBL net_amount), Steuerkategorie (tax_category), Steuersatz (tax_rate) und Währung (invoice_currency).agorum_accounting_document_payment_method), IBAN und BIC.tax_id_1, total_tax_rate_1, total_net_amount_1, total_tax_amount_1, bis zu drei Sätze) sowie die Rechnungssummen.| Bedingung | Feld | Erklärung |
|---|---|---|
| Dokumenttyp 381 oder 384 | agorum_accounting_document_billing_reference (BT-25) |
Bezug auf die Ursprungsrechnung; wird von der Vorprüfung nicht verlangt, aber vom Validator gemeldet |
| Steuerkategorie E, AE, K, G oder O | agorum_accounting_document_total_tax_exemption_reason_code_<n> (BT-121) bzw. _reason_<n> (BT-120) |
Befreiungsgrund je Steuersatz auf Rechnungsebene, etwa VATEX-EU-AE; Steuersatz 0 |
| Zahlungsart 59 (SEPA-Lastschrift) | – | Mandatsreferenz und Gläubiger-ID werden derzeit nicht unterstützt |
| Rechnungsart | type_code (BT-3) | Besonderheiten |
|---|---|---|
| Rechnung | 380 | Standardfall |
| Teilrechnung | 326 | vorausgegangene Teilrechnungen in agorum_accounting_document_billing_references |
| Gutschrift | 381 | Bezug auf die Ursprungsrechnung in agorum_accounting_document_billing_reference (BT-25); in UBL entsteht ein CreditNote-Dokument; Beträge positiv angeben |
| Rechnungskorrektur | 384 | Bezug auf die korrigierte Rechnung in BT-25 ist Pflicht (Regel BR-DE-26); in UBL entsteht ein CreditNote-Dokument |
| Selbst ausgestellte Rechnung (Gutschriftverfahren) | 389 | Der Käufer stellt die Rechnung aus; Verkäufer- und Käuferangaben bleiben in ihren Rollen |
Hinweis: Im CII-Format (XRechnung CII und ZUGFeRD) ist nur eine vorausgegangene Rechnung zulässig. Geben Sie mehrere an, wird die erste übernommen und die übrigen werden unter suppressed gemeldet. Im UBL-Format sind mehrere Bezüge möglich.
Rechnungsbegründende Unterlagen wie Stundennachweise oder Lieferscheine können Sie in die XML einbetten. Übergeben Sie die Dateien bei createInvoiceRaw im Parameter attachments; sie werden base64-codiert als zusätzliche Dokumente (BG-24) geschrieben. Die Größe eines Anhangs ist standardmäßig auf 25 MB begrenzt. Prüfen Sie zusätzlich die Grenzen Ihres Empfängers oder Rechnungsportals, die oft deutlich niedriger liegen.
| Meldung | Ursache | Abhilfe |
|---|---|---|
| Invoice cannot be generated due to necessary information: [...] | Pflichtfelder fehlen | Die Liste nennt die fehlenden Schlüssel. Ergänzen Sie die Felder und rufen Sie checkRequiredFields erneut auf. |
| [BR-CO-*] Summen stimmen nicht | Netto-, Steuer- oder Bruttosummen passen nicht zu den Positionen | Summen aus den Positionen nachrechnen; Rundung beachten |
| [BR-DE-15] Käuferreferenz fehlt | BT-10 ist bei XRechnung Pflicht | agorum_accounting_document_buyer_reference_number setzen |
| Schema-Fehler beim Empfänger, obwohl die eigene Prüfung grün war | ZUGFeRD im Profil EXTENDED an einen Empfänger mit EN-16931-Prüfung | Profil en16931 verwenden, siehe undefined>Profilsteuerung |
| Peppol-Rechnung wird gegen XRechnung-Regeln geprüft | Keine Peppol-Spezifikationskennung gesetzt | agorum_accounting_document_function_code auf die Peppol-BIS-Kennung setzen |