# Bedienung und technische Dokumentation Stand: 16.10.2026 · Version 1.0 ## 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/.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](docs/beispiel-workflow-halian.md) 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 ` --help` zeigen alle Parameter. ```bash # 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_.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](https://www.bundesfinanzministerium.de/Content/DE/FAQ/e-rechnung.html). ### Ä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: ```yaml 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 ```bash 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.