227 lines
13 KiB
Markdown
227 lines
13 KiB
Markdown
# 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/<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](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 `<befehl> --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_<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](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.
|