====== kassensichv.manager ====== → [[lyx_-_programmiersprache:units:kassensichv|Zurück zur KassenSichV-Übersicht]] Haupteinstiegspunkt für Kassensoftware-Entwickler. Der ''TseManager'' orchestriert den vollständigen TSE-Transaktionsablauf: Transaktion öffnen → TSE signieren lassen → QR-Code generieren. **Wichtig:** Der ''TseManager'' ist **nicht thread-sicher**. Pro physische Kasse genau eine Instanz verwenden. ===== Import ===== import kassensichv.types; import kassensichv.manager; ===== Erzeugen / Freigeben ===== Der Manager wird immer mit einem konkreten Provider erstellt. Welcher Provider verwendet wird, bestimmt sich aus der verwendeten ''TseXxxNew''-Funktion (aus ''kassensichv.mock'', ''kassensichv.rest'' oder ''kassensichv.file''). // (Import des jeweiligen Providers nötig — z.B. kassensichv.mock) pub fn TseManagerFree(mgr: int64): void; Der Manager übernimmt den Besitz des Providers. ''TseManagerFree'' gibt beides frei. ===== Einfacher Kassenbon (ProcessBeleg) ===== pub fn TseProcessBeleg(mgr: int64, beleg: int64): int64; // Gibt *SigErgebnis zurück (allokiert) — caller muss SigErgebnisFree aufrufen // Wirft bei Fehler: errorMsg in SigErgebnis und success=0 Ablauf intern: - ''StartTransaction'' → TSE öffnet Transaktion, vergibt Zähler - ''FinishTransaction'' → TSE signiert mit ECDSA-Schlüssel - QR-Code-String nach BSI TR-03153 Anhang A generieren Bei Fehler in ''FinishTransaction'' ist die TSE-Transaktion offen — das ist ein **Compliance-Problem**. Der Manager liefert ''success=0'' und ''errorMsg'' zurück; die Kassensoftware muss diese Situation behandeln (manuell abschließen oder stornieren). import kassensichv.types; import kassensichv.mock; import kassensichv.manager; fn main(): int64 { var mgr: int64 := TseMockNew(); var beleg: BelegDaten; beleg.prozessTyp := PROZESSTYP_KASSENBELEG; beleg.kassenNr := "KASSE-001"c; beleg.prozessDaten := "Kaffee;2.50_0.00_0.00_0.00_0.00"c; beleg.umsatz := 250; var sig: int64 := TseProcessBeleg(mgr, addr beleg); if sig == 0 then { PrintLn("Signierung fehlgeschlagen"c); TseManagerFree(mgr); return 1; } var s: SigErgebnis := (sig as *SigErgebnis)^; if s.success == 0 then { Print("Fehler: "c); PrintLn(s.errorMsg as pchar); } else { PrintLn(s.qrCode as pchar); } SigErgebnisFree(sig); TseManagerFree(mgr); return 0; } ===== Mehrstufige Vorgänge ===== Für Tischbewirtung, Bestellungen mit Zwischenständen oder Split-Zahlungen: ==== TseOpenBeleg ==== pub fn TseOpenBeleg(mgr: int64, beleg: int64): int64; // Gibt pchar TransId zurück (allokiert) — nach TseCloseBeleg mit free() freigeben // Befüllt beleg.transId und beleg.startZeit ==== TseUpdateBeleg ==== pub fn TseUpdateBeleg(mgr: int64, transId: int64, beleg: int64): int64; // Gibt *SigErgebnis zurück (Zwischenstand, ohne QR-Code) — SigErgebnisFree aufrufen // Optional — kann mehrfach zwischen Open und Close aufgerufen werden ==== TseCloseBeleg ==== pub fn TseCloseBeleg(mgr: int64, transId: int64, beleg: int64): int64; // Gibt *SigErgebnis zurück (allokiert, mit QrCode befüllt) — SigErgebnisFree aufrufen // Wirft bei Fehler: success=0 — offene Transaktion bei TSE → Compliance-Problem! **Vollständiges Beispiel — Tischbestellung:** fn Tischbestellung(mgr: int64): void { var beleg: BelegDaten; beleg.prozessTyp := PROZESSTYP_KASSENBELEG; beleg.kassenNr := "KASSE-001"c; // Transaktion öffnen var transId: int64 := TseOpenBeleg(mgr, addr beleg); // Vorspeise geliefert beleg.prozessDaten := "Vorspeise;8.00_0.00_0.00_0.00_0.00"c; beleg.umsatz := 800; var zwi: int64 := TseUpdateBeleg(mgr, transId, addr beleg); SigErgebnisFree(zwi); // Hauptgang geliefert + Kassenbon abschließen beleg.prozessDaten := "Vorspeise+Hauptgang;28.00_0.00_0.00_0.00_0.00"c; beleg.umsatz := 2800; var sig: int64 := TseCloseBeleg(mgr, transId, addr beleg); var s: SigErgebnis := (sig as *SigErgebnis)^; PrintLn(s.qrCode as pchar); SigErgebnisFree(sig); free(transId); } ===== DSFinV-K-Export ===== pub fn TseExportAuditData(mgr: int64, targetPath: int64, kassenNr: int64): int64; // 1 = Export erfolgreich, 0 = Fehler (Pfad nicht schreibbar, Provider-Fehler) // Erzeugt: {targetPath}/tse_export.tar (TSE-interne Daten, signiert) // {targetPath}/index.json (DSFinV-K-Metadaten) Das TAR-Archiv stammt direkt von der TSE und ist intern signiert. Es darf **nicht verändert** werden — Finanzamt-Prüfsoftware (IDEA) validiert die TSE-Signatur über die Dateiintegrität. ''index.json'' enthält: { "dsfinvk_version": "2.3", "tse_serial": "...", "kasse_id": "KASSE-001", "export_timestamp": "2026-06-12T09:00:00Z" } var ok: int64 := TseExportAuditData(mgr, "/var/kassensichv/export"c, "KASSE-001"c); if ok == 0 then { PrintLn("Export fehlgeschlagen — Verzeichnis nicht schreibbar?"c); } ===== Status und Seriennummer ===== pub fn TseGetStatus(mgr: int64): int64; // Gibt pchar JSON-Status-String zurück (allokiert) — mit free() freigeben // Felder: provider, serial, status, ggf. provider-spezifische Details pub fn TseGetSerial(mgr: int64): int64; // Gibt pchar TSE-Seriennummer zurück (allokiert) — mit free() freigeben var status: int64 := TseGetStatus(mgr); PrintLn(status as pchar); // Beispiel: {"provider":"RestTseProvider","serial":"XYZ123","status":"connected"} free(status); var serial: int64 := TseGetSerial(mgr); Print("TSE: "c); PrintLn(serial as pchar); free(serial); ===== Funktions-Übersicht ===== ^ Funktion ^ Parameter ^ Rückgabe ^ Beschreibung ^ | ''TseManagerFree'' | ''mgr'' | — | Manager + Provider freigeben | | ''TseProcessBeleg'' | ''mgr, beleg'' | ''*SigErgebnis'' | Einzel-Transaktion (Start+Finish+QR) | | ''TseOpenBeleg'' | ''mgr, beleg'' | ''pchar'' TransId | Transaktion öffnen | | ''TseUpdateBeleg'' | ''mgr, transId, beleg'' | ''*SigErgebnis'' | Transaktion aktualisieren | | ''TseCloseBeleg'' | ''mgr, transId, beleg'' | ''*SigErgebnis'' | Transaktion abschließen | | ''TseExportAuditData'' | ''mgr, path, kassenNr'' | ''int64'' (1/0) | DSFinV-K-Export | | ''TseGetStatus'' | ''mgr'' | ''pchar'' JSON | TSE-Status abfragen | | ''TseGetSerial'' | ''mgr'' | ''pchar'' | TSE-Seriennummer | ----- Letzte Aktualisierung: 2026-06-12