Files
einvoice/Documentation.md
T

21 KiB

Bedienung und technische Dokumentation

Stand: 19.10.2026 · Version 1.1

Desktop-Oberfläche

einvoice-ui ergänzt die Konsole um Vorlagen, Kundenformular, mehrere Positionen, Betragsübersicht, Entwurfsvorschau und eingebettete fertige PDF. Installation: einvoice --update --apply --with-gui, danach python3 scripts/install_commands.py --desktop. Die GUI nutzt dieselbe Erstellung und Validierung wie die Konsole. Vollständige Bedienungs- und Entwicklungsdokumentation.

Einrichtung und persönliche Vorlagen

Die README enthält den sofort nutzbaren Ein-Aufruf-Ablauf mit einvoice --create. Installation aus dem Repository mit pip install -e '.[pdf]'; Java wird für Mustang benötigt. setup-mustang installiert die geprüfte Referenzversion 2.26.0 aus Maven Central mit SHA1-Abgleich. Der Abgleich prüft die Downloadintegrität; er ist keine Signaturprüfung. mustang-update zeigt neuere Versionen, mustang-update --apply installiert sie. Danach eine Testrechnung erneut prüfen. JR_EINVOICE_MUSTANG_JAR überschreibt den Standardpfad. Downloads erfolgen nur bei Setup/Update; Generierung und Validierung laufen lokal ohne Upload der Rechnungsdaten.

Vorlagen werden in dieser Reihenfolge zusammengeführt:

  1. examples/invoice.init.yaml.
  2. Versionierte presets/seller.default.yaml mit Beispieldaten.
  3. Lokale private/presets/seller.default.yaml.
  4. Lokale private/presets/customers/<kunde>.yaml, sonst die versionierte Kunden-Datei, sonst presets/customers.yaml.
  5. Rechnungsnummer, Datum, Zahlungsziel und Monats-/Stundenangaben des Befehls.

JR_EINVOICE_HOME=/absoluter/pfad setzt das private Datenverzeichnis. JR_EINVOICE_PRESETS=/absoluter/pfad setzt ein anderes Verzeichnis für die lokalen Vorlagen (gleiche Unterstruktur). Persönliche Daten nicht in die versionierten Beispieldateien eintragen. private/, invoices/, die virtuelle Umgebung und Ausgabeordner sind gitignoriert. Externe Rechnungsordner separat gegen versehentliches Committen sichern. Die lokale IDV-Vorlage ist nur historischer Bestand; keine Empfängeradresse ist dafür erforderlich.

Durchgängiges Praxisbeispiel

Halian GmbH: C# Entwicklung Bank Projekt, Oktober 2026 zeigt die Rechnungserstellung, das Anhängen der PDF-Datei und den manuellen Versand an invoice@halian.com, einschließlich Betreff, Textvorlage und optionalem EML-Entwurf. Die Beispielannahmen (120 Stunden und 85 EUR netto „all in“ zuzüglich Umsatzsteuer) sind dort ausdrücklich gekennzeichnet. Halian ist hier kein bestätigter Kunde.

Befehle

jr-einvoice --help und <befehl> --help zeigen alle Parameter.

# Vollständig erzeugen und validieren (normaler Ablauf):
einvoice --create --Customer "Kundenfirma GmbH" \
  --Entry "Geleistete Stunden Oktober 2026" --Volume 120 --Price "85,00 €"

# Expertenablauf für mehrere Positionen / manuell bearbeitete YAML-Dateien:
jr-einvoice init private/invoices --auto-folder --open
jr-einvoice generate /pfad/zum/rechnungsordner --json
jr-einvoice email /pfad/zum/rechnungsordner --to rechnung@empfaenger.example

Ein-Aufruf-Erstellung

einvoice ist ein eigener Konsolenbefehl. Die Optionen --Customer, --Entry, --Volume und --Price sind erforderlich. Der Kunde wird über den Namen oder einen angezeigten Schlüssel aus einvoice --customers gefunden. Für neue Kunden erfasst der Befehl einmalig eine vollständige Rechnungsanschrift. Alternativ können diese Daten mit --Street, --PostalCode, --City und optional --Country, --Email, --VatId übergeben werden. In Skripten führen fehlende Daten zu einer konkreten Fehlermeldung; es gibt keine erfundenen Adressen oder hängenden Eingabeaufforderungen. Adressoptionen überschreiben keine bereits gespeicherten Kunden. Deren Stammdaten gezielt in der lokalen Kundendatei bearbeiten. Der Kunde IDV ist ein ehemaliger Kunde und hat keine besondere Rolle im Ablauf.

--Price ist der Nettopreis pro Einheit. Deutsche Schreibweise (85,00 €, 1.234,56 EUR) und ungegliederte Dezimalpunkt-Schreibweise (85.00) sind zulässig. --Volume und --Tax verstehen dieselben Dezimalzahlen. Ohne Dezimalkomma gilt ein Punkt als Dezimalpunkt; 1.234 bedeutet daher 1,234 und nicht 1234. Gemischte oder ungültige Angaben werden abgewiesen. Standardwerte: --Unit HUR, --Tax 19, --DueDays 30, Rechnungsdatum heute. Preis, Menge und Steuer werden ausdrücklich angegeben bzw. verwenden diese dokumentierten Standardwerte; ein alter kundenspezifischer Stundensatz wird nicht unbemerkt übernommen.

Ein deutscher Monatsname plus Jahr in --Entry, z. B. „Oktober 2026“, ergibt den vollständigen Leistungsmonat. --Month YYYY-MM setzt ihn ausdrücklich; --ServiceDate YYYY-MM-DD überschreibt die automatische Erkennung durch ein Einzeldatum. Beide expliziten Optionen zusammen sind nicht zulässig. Ohne Monat oder Leistungsdatum gilt das Rechnungsdatum als Leistungsdatum. Die Konsole zeigt den verwendeten Zeitraum; tatsächliche Leistungsdaten vor Versand prüfen.

Nummern werden unter Dateisperre im gewählten --root automatisch als JR-JJJJ-NNNN vergeben. Alle gespeicherten YAML-Rechnungen auf der ersten Ebene werden auf bereits verwendete Nummern geprüft; --Number kann eine eigene freie Nummer setzen. Bei fehlgeschlagenem PDF-Build bleibt der Entwurf erhalten und reserviert seine Nummer. Der Befehl meldet einen Fehler und veröffentlicht kein fertiges Anhang-PDF. In out/logs/run.log stehen Details. Zum Korrigieren und Wiederholen den betreffenden Entwurf mit jr-einvoice generate aufbauen; keinen bereits versandten Datensatz verändern.

Nach erfolgreicher PDF/A- und XML-Validierung wird das vollständige hybride PDF zusätzlich als Rechnung_<Nummer>.pdf im Rechnungsordner bereitgestellt. Diese Datei direkt an eine E-Mail anhängen. out/invoice.pdf ist lediglich die Sichtkopie. out/manifest.json hält SHA-256-Prüfsummen einschließlich des Anhang-PDFs fest. --json schreibt nur ein JSON-Ergebnis mit Nummer, Ordner, PDF, Prüfbericht, Log und technical_validation: valid nach stdout. Keine automatische Mailübertragung.

Die Konsole bestätigt „PDF/A und EN16931-XML technisch gültig“. Sie behauptet keine vollständige rechtliche oder steuerliche Prüfung der Geschäftsdaten; siehe BMF-FAQ zur Validierung.

Älterer Monatsentwurf

Der ergänzende jr-einvoice monthly-Befehl bleibt für gespeicherte Stundenvorlagen verfügbar; der neue Standard ist einvoice --create.

monthly übernimmt genau eine Stundenposition (HUR) aus der Kundenvorlage, setzt deren Menge und deutschen Monatsnamen sowie Anfang/Ende des Monats. --date setzt ein abweichendes Rechnungsdatum, ansonsten gilt heute. --rate überschreibt den Nettostundensatz. Ungültige Monatsentwürfe hinterlassen keinen Rechnungsordner.

Explizite Nummern dürfen noch nicht vergeben sein. monthly prüft YAML-Rechnungen auf der ersten Ordnerebene desselben Stamms, auch bei anderen Kunden, und verhindert Überschreiben. Das optionale Nummernvorschlagen von init --auto-folder verwendet weiter das Schema YYYY-NNNN aus Ordnernamen. Es kennt die bisherigen YYYY-MM-PDFs nicht. Für den Wechsel daher eine freie Nummer ausdrücklich setzen; keine bereits versandte Rechnung unter gleicher Nummer neu ausstellen. Die lokale Ordneranlage ist per Dateisperre serialisiert; kein verteiltes Rechnungsregister.

init --print-path-only, generate --print-artifacts-only und generate --json schreiben maschinenlesbare Ergebnisse nach stdout; Logs laufen nach stderr. --open verwendet $EDITOR, danach verfügbare Editoren. Ein unbekannter Kunde führt zu einem Fehler statt zu einer Rechnung mit generischem Empfänger.

YAML und Beträge

Die vollständige Ausgangsvorlage steht in examples/invoice.sample.yaml. Zusätzlich werden folgende optionale Meta-Felder unterstützt:

meta:
  # ... invoice_number, invoice_date, service_date, currency ...
  service_period_start: '2026-10-01'
  service_period_end: '2026-10-31'
  buyer_reference: 'Kundenreferenz'
  order_reference: 'Bestellnummer'

Alle Pflichtangaben einschließlich Leistungsbeschreibung und Zeitraum gelangen in PDF und XML. Für Monatsrechnungen steht service_date auf dem Monatsende. Bei Teilmonaten den tatsächlichen Zeitraum setzen. payment.reference ist der Verwendungszweck, keine Bestellnummer. Kunden- und Bestellreferenzen stehen in den eigenen Meta-Feldern. Ein B2B-Empfänger benötigt keine erfundene Leitweg-ID.

Geld, Mengen und Steuersätze verwenden Decimal. Jede Nettoposition wird kaufmännisch auf Cent gerundet; je Steuersatz wird die Steuer aus der Summe der gerundeten Nettopositionen berechnet und auf Cent gerundet. PDF und XML verwenden dieselbe Berechnung. Dezimalpunkt verwenden; besonders genaue Mengen/Preise in YAML als Zeichenkette angeben (quantity: '72.5'). Leere Positionen, nicht endliche Zahlen, negative Preise, Nullsteuersätze, unbekannte YAML-Felder und ungültige IBAN-Prüfsummen werden abgewiesen. Der Validator prüft zusätzlich Format und Geschäftsregeln.

PDF/A, XML und Validierung

WeasyPrint erzeugt PDF/A-3b. Mustang kombiniert diese Sichtkopie mit dem CII-D16B-XML, Profil EN16931 (--format fx --version 1 --profile E). Die konkrete Kombination wurde mit Mustang 2.26.0 einschließlich PDF/A und eingebettetem XML erfolgreich geprüft. Die CLI-Formatversion 1 bezeichnet Factur-X, nicht ZUGFeRD 1. Es wird keine Behauptung einer Zertifizierung oder vollständigen Unterstützung aller neuen ZUGFeRD-2.5.2-Funktionen abgeleitet.

Der frühere wkhtmltopdf-Fallback bleibt für eine Sichtkopie verfügbar, garantiert aber kein PDF/A. Ohne gültiges PDF/A darf die abschließende Prüfung nicht bestehen. Für den produktiven Weg WeasyPrint verwenden.

generate kombiniert und validiert immer. Die Python-Pipeline kann für interne Anwendungsfälle auch nur Sichtkopie und XML erzeugen. Ein Erfolg erfordert einen parsebaren Mustang-Bericht mit XML-Prüfabschnitt und ausschließlich gültigen Zusammenfassungen einschließlich Gesamtergebnis. Ein Exitcode 0 allein genügt nicht. Bei fehlgeschlagener Validierung bleibt der Bericht erhalten und das nicht freigegebene hybride PDF wird entfernt. Alte Mailentwürfe werden bei einem neuen Build verworfen. Pro Lauf stehen Details und Mustang-Ausgaben in out/logs/run.log.

Für Eingänge kann validate XML und hybride PDF prüfen. Eine normale PDF-Datei wird nicht als strukturierte E-Rechnung akzeptiert. Quellen bleiben unverändert; Berichte an einem eigenen Pfad aufbewahren. Inhaltliche Prüfung (Leistung, Parteien, Betrag, Steuersatz, Doppelrechnung) bleibt zusätzlich erforderlich.

Versand und Aufbewahrung

email erzeugt die Standardausgabe erneut aus invoice.yaml und legt erst nach erfolgreicher Prüfung invoice.eml an. Absender kommt aus seller.email, Empfänger aus buyer.email oder --to. Die Mail enthält nur das hybride PDF als Rechnungsanhang; XML ist darin eingebettet. X-Unsent: 1 kennzeichnet den Entwurf. Kein SMTP-Zugang, kein Passwort und kein automatischer Versand sind nötig. Das konkrete Öffnen als Entwurf hängt vom Mailprogramm ab. Versand und Zustellnachweis erfolgen dort.

manifest.json enthält SHA-256-Prüfsummen von YAML, XML, hybridem PDF, Bericht und EML. Es unterstützt die Integritätskontrolle, schafft aber allein kein unveränderbares Archiv. Nach Versand den vollständigen Rechnungsordner und die gesendete Originalmail samt Versandnachweis in die bestehende gesicherte Ablage übernehmen. Versandte Rechnungen nicht durch erneutes generate überschreiben. Für Berichtigungen einen fachlich abgestimmten Prozess verwenden. Das Tool verwaltet keine Stornos.

Prüfung der Überarbeitung

python -m unittest discover -s tests -v
# Einschließlich echter PDF-/XML-/Mail-Prüfung durch Mustang:
JR_EINVOICE_INTEGRATION=1 python -m unittest discover -s tests -v

Die Tests decken deutschen Preisparser, neue/wiederverwendete Kunden, Ein-Aufruf-Nummernvergabe, Abbruch ohne fertigen PDF-Anhang sowie dezimale Rundung, mehrere Steuersätze, Pflichtdaten und ungültige Zahlen/IBAN, XML-Inhalte, HTML-Escaping, Monatsgrenzen einschließlich Schaltjahr, Nummernkollisionen, unbrauchbare oder widersprüchliche Validierungsberichte sowie veraltete Mailentwürfe ab. Der echte Mustang-Lauf ist ein zusätzlicher Integrationstest und erfordert Java und das lokale Jar.

Lokal wurde eine Testrechnung mit den Juli-Beispielwerten erstellt: 75 Stunden zu 85 EUR → 6.375,00 EUR netto + 1.211,25 EUR USt = 7.586,25 EUR. Nummer TEST-2026-07, keine neue echte Rechnung. Der Mailtest verwendet die nicht zustellbare Adresse rechnung@example.invalid. Die alten PDF-Rechnungen wurden nicht verändert.

Bewusster Funktionsumfang

Normale positive Dienstleistungsrechnungen in EUR mit positiver Umsatzsteuer und mehreren Steuersätzen sind unterstützt. Nicht implementiert sind steuerfreie Positionen, Kleinunternehmer, Reverse Charge, Abschläge/Anzahlungen, Skonto/Zuschläge/Rabatte, Gutschriften/Storno, Fremdwährungs-Steuerumrechnung, XRechnung-CIUS-Ausgabe, Peppol, DATEV-API und automatischer Postfacheingang. Diese Fälle nicht durch bloße Freitexthinweise nachbilden. Das vorhandene CII-XML ist keine XRechnung, auch wenn beide Formate EN16931 verwenden. Aufbewahrung/Backups und fachliche Freigabe müssen in den betrieblichen Ablauf eingebunden werden.

Updates und Rollback

Der empfohlene Update-Einstieg für diesen Linux-Checkout ist python3 scripts/update.py (nur Standardbibliothek, unabhängig von der venv). Alternativ: ./bin/einvoice --update. Mit --apply aktivieren, mit --status den aktiven/vorherigen Stand anzeigen, mit --rollback zurückwechseln. --mustang-version 2.26.0 erlaubt eine gezielte stabile Mustang-Version. Ohne Versionsvorgabe wird Maven release bevorzugt; Vorabversionen werden abgewiesen.

  1. Exklusive Dateisperre verhindert gleichzeitige Wartungsläufe.
  2. Neue venv unter .runtime/releases/<Zeit-ID>/venv erstellen und Projekt als Wheel installieren, einschließlich PDF-Extra und transitiver Abhängigkeiten. pyproject.toml ist die maßgebliche Abhängigkeitsdefinition. pip wählt die neuesten zum Interpreter und zu diesen Vorgaben passenden Versionen.
  3. Mustang von Maven herunterladen und veröffentlichte SHA1-Prüfsumme vergleichen. Das prüft Übertragungsfehler, ist keine unabhängige Signaturprüfung.
  4. Versionen vergleichen und Installationsbericht, vollständigen Paketstand (requirements.freeze.txt) sowie Manifest mit Quell-Commit und JAR-SHA256 speichern.
  5. pip check, WeasyPrint-PDF, beide CLI-Hilfen und alle Unittests einschließlich echter Integrationstests ausführen. Dazu gehören PDF/A, eingebettetes XML, EML-Anhang, neuer/bekannter Kunde sowie Ablehnung falscher Summen, Einheiten und PDFs ohne Rechnungs-XML. Tests nutzen temporäre Muster-/Kundendaten. -I und ein fremdes Arbeitsverzeichnis verhindern, dass der Checkout die tatsächlich installierte Anwendung bei den Tests verdeckt.
  6. Nur bei --apply: bisherigen Stand sichern und .runtime/current atomar auf den Kandidaten setzen. Dieselben Healthchecks nach der Aktivierung wiederholen; bei Fehler/KeyboardInterrupt sofort den bisherigen Zeiger wiederherstellen.

bin/einvoice und bin/jr-einvoice lösen den Zeiger pro Aufruf einmal auf und verwenden Python und Mustang aus demselben Release. Nutzerablage bleibt standardmäßig private/ im Checkout, auch bei Wheel-Installation; JR_EINVOICE_HOME und JR_EINVOICE_PRESETS werden respektiert. Vor dem ersten verwalteten Update nutzen die Starter .venv; beim ersten Aktivieren wird diese unverändert verlinkt und die bisherige Mustang-JAR kopiert. Diese erste Baseline ist noch die ursprüngliche Entwicklerumgebung: nicht löschen/verändern, wenn sie als Rückfall benötigt wird. Spätere Releases sind eigenständige, fest installierte Wheel-Umgebungen.

Fehlende Downloads, defekte Prüfsummen, Resolverfehler, Timeouts und fehlgeschlagene Tests führen zu Exitcode 1. Erfolgreiche Wartung liefert 0. Kandidaten, vorherige Releases und Logs bleiben zur Diagnose erhalten; es gibt kein automatisches Löschen. Nach Abbruch durch SIGKILL/Stromausfall zeigt current auf einen vollständigen vorherigen oder neuen Stand; eine noch ausstehende Nachprüfung wird nicht automatisch nachgeholt. Bei Bedarf --rollback ausführen. Rollback prüft den Zielstand vorab; ist er wegen externer Änderungen defekt, bleibt der aktuelle Zeiger erhalten.

Updates ändern keine Rechnungen, Kunden oder Rechnungsnummern. Rollback umfasst Python-Pakete, den installierten Anwendungscode und Mustang; keine Git-Änderungen, privaten Daten, Python-Systemversion, Java oder nativen Bibliotheken. Nach Systemupdates muss eine bisherige venv ggf. neu aufgebaut werden. Systemupdates auf Arch als vollständiges Update über sudo pacman -Syu durchführen und danach den Prüflauf starten. Der Updater führt weder sudo noch Systempaketänderungen aus.

Es gibt bewusst keinen Hintergrundtimer: neue Stände werden explizit geprüft und übernommen. Zum Beispiel vor dem nächsten Rechnungslauf oder monatlich prüfen. Neue Projektversionen zunächst separat über Git holen, danach den Updater starten; der Updater führt kein git pull aus. Uncommittete Quellen werden mit eingebaut, der Manifest-Commit allein beschreibt diese daher nicht vollständig. Die bisherigen setup-mustang/mustang-update --apply sind einfache Direktinstallationen ohne Transaktionsschutz und verwalten die neue Laufzeit nicht; für Updates den gemeinsamen Ablauf verwenden. Eine Wheel-Installation außerhalb des Checkouts besitzt diesen Checkout-Updater nicht.

Technische Grundlagen: pip Versionsauflösung und Installationsbericht, Python venv und feste Umgebungspfade. Umgebungen bleiben deshalb an ihrem Erstellungsort; nur der Zeiger wird gewechselt.

Konsolenbefehle installieren

Einmal im Checkout python3 scripts/install_commands.py ausführen. Der Installer benötigt kein sudo und verlinkt einvoice sowie jr-einvoice nach ~/.local/bin. Die verlinkten Starter finden den Checkout auch beim Aufruf aus einem anderen Verzeichnis und verwenden den aktiven Update-/Rollback-Stand. Beide Befehle werden mit --help geprüft. Bei Fehlern setzt der Installer seine Änderungen zurück. Vorhandene andere Dateien/Symlinks werden unter *.before-einvoice-<Zeit-ID> gesichert; bereits korrekt eingerichtete Links bleiben erhalten.

# Einmalig:
cd /home/johannes/localdev/einvoice
python3 scripts/install_commands.py

# Danach auch außerhalb des Checkouts:
einvoice --help
einvoice --customers
einvoice --update --status
einvoice --update --apply
einvoice --update --rollback
jr-einvoice --help

Abweichender Zielordner: --bin-dir /absoluter/pfad. Falls dieser Ordner nicht im PATH steht, zeigt der Installer die passende Export-Zeile an; dauerhaft in die eigene Shell-Konfiguration übernehmen. Auf Johannes' Rechner ist ~/.local/bin bereits im PATH, daher ist keine Änderung der Shell-Konfiguration nötig. Bei einem alten Shell-Cache rehash (zsh) oder hash -r (bash) verwenden. Eine aktivierte .venv kann den alten Einstieg vorziehen; mit deactivate die verwalteten Befehle nutzen. Der Checkout muss am Installationsort erhalten bleiben. Nach Verschieben den Installer am neuen Ort erneut ausführen. Die Starter benötigen bash, readlink und Python 3; diese sind auf dem vorgesehenen Linux-System vorhanden.

Office-Unabhängigkeit und LibreOffice

Die Quell-, Vorlagen- und Datenformate der Anwendung sind YAML, HTML/Jinja2, SVG und Markdown. Erzeugt werden PDF/A-3, strukturiertes XML, Prüfberichte, JSON-Manifeste und optional EML. Weder DOC/DOCX, XLS/XLSX, PPT/PPTX noch COM-/Microsoft-Office-APIs werden verwendet. Es gibt keine Abhängigkeit von Word, Excel, Outlook oder einer Microsoft-365-Lizenz. Die Python-Abhängigkeiten und die externen Werkzeuge WeasyPrint/Mustang/Java benötigen keine Office-Installation.

Für diese Rechnungslösung muss deshalb beim Wechsel zu LibreOffice nichts nach ODT/ODS konvertiert werden. ODF-Import/-Export ist keine Funktion des Tools; Dokumentvorlagen werden weiterhin als HTML/Jinja2 bearbeitet, Daten als YAML. Die versandfertige E-Rechnung ist das validierte PDF mit eingebettetem XML. Dieses Original nicht in Office/LibreOffice bearbeiten oder als neues PDF exportieren, da XML-Einbettung und PDF/A-Eigenschaften dabei verloren gehen können.

Der optionale EML-Entwurf ist eine Datei ohne Outlook-Automation. Mailprogramm, Mailkonto, Zugang und tatsächlicher Versand liegen außerhalb der Toolchain. Die Prüfung betrifft dieses eInvoice-Projekt; andere persönliche oder betriebliche Office-Dateien und Microsoft-365-Dienste wurden damit nicht geprüft oder migriert.