From f51fde6a235751f7c0e9781facb0e0d0624f9788 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 31 Aug 2026 03:30:28 +0200 Subject: [PATCH] Add Workflows feature with Swiss QR Code validation Introduced the `Client.Workflows` feature to enable combined operations with pre-validation. Added the method `ExtractSwissQrCodeValidatedAsync()` for extracting Swiss QR Code data with validation in one step. Updated the README to document the new feature, including usage examples in C#, VB.NET, and PowerShell, details on the `throwIfInvalid` parameter, and method signature. Added the method to the API Endpoints section with a note about its current `NotImplementedException` status. Clarified the use of `[Obsolete]` for unimplemented endpoints. Enhanced the PowerShell note to recommend threading for long-running operations. --- DocumentService.Client/README.md | 99 ++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/DocumentService.Client/README.md b/DocumentService.Client/README.md index ae2a9bd..4427b3c 100644 --- a/DocumentService.Client/README.md +++ b/DocumentService.Client/README.md @@ -9,6 +9,7 @@ - **Separate Clients pro Fachbereich**: `Client.Validation`, `Client.Attachment`, `Client.Operations`, `Client.SwissQrCode`, `Client.Zugferd`, `Client.Conversion` - **Dualer Eingabe-Support**: Multipart (Stream) und Base64 (byte[]) für alle Endpunkte - **Stark typisierte Modelle**: Gemeinsame Request/Response-DTOs mit XML-Dokumentation +- **Workflows**: `Client.Workflows` – kombinierte Operationen mit vorgelagerter Validierung (z. B. Swiss QR Code mit automatischer PDF-Prüfung) ## Installation @@ -155,6 +156,7 @@ Client.OnReconfigure = OnReconfigure.Ignore | `Client.SwissQrCode` | `ISwissQrCodeClient` | Schweizer QR-Code | | `Client.Zugferd` | `IZugferdClient` | ZUGFeRD-Rechnungen | | `Client.Conversion` | `IPdfConversionClient` | PDF-Konvertierung *(geplant)* | +| `Client.Workflows` | `IWorkflowsClient` | Kombinierte Operationen | Jeder Zugriff auf eine dieser Eigenschaften erstellt einen neuen DI-Scope. Clients sind **nicht** für die dauerhafte Speicherung als Felder gedacht – jeder Aufruf holt sich eine frische Instanz. @@ -179,6 +181,102 @@ Alle Beispiele nutzen ausschließlich den statischen `Client`-Einstiegspunkt. Vo --- +### Workflows – Kombinierte Operationen + +`Client.Workflows` fasst häufig benötigte Abläufe zusammen, die mehrere Einzelendpunkte orchestrieren. Die Validierung läuft dabei immer zuerst – die Folgeaktion wird nur bei einem gültigen Dokument ausgeführt. + +> Für Anwendungsfälle wie den **eParser** (Swiss QR Bill aus Eingangsrechnungen lesen) ist dies der empfohlene Einstiegspunkt. + +#### Swiss QR Code – mit vorgelagerter Validierung + +```csharp +using DocumentService.Client; + +// Variante A: byte[] +byte[] pdfBytes = await File.ReadAllBytesAsync("rechnung.pdf"); +var result = await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes); + +Console.WriteLine($"Betrag: {result?.Bill?.Amount} {result?.Bill?.Currency}"); +Console.WriteLine($"Empfänger: {result?.Bill?.Creditor?.Name}"); + +// Variante B: Stream +using var stream = File.OpenRead("rechnung.pdf"); +var result2 = await Client.Workflows.ExtractSwissQrCodeValidatedAsync(stream); + +// Variante C: Dateipfad +var result3 = await Client.Workflows.ExtractSwissQrCodeValidatedAsync("rechnung.pdf"); +``` + +```vbnet +Imports DocumentService.Client + +' Variante A: byte[] +Dim pdfBytes = System.IO.File.ReadAllBytes("rechnung.pdf") +Dim result = Await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes) + +Console.WriteLine($"Betrag: {result?.Bill?.Amount} {result?.Bill?.Currency}") +Console.WriteLine($"Empfänger: {result?.Bill?.Creditor?.Name}") + +' Variante B: Dateipfad +Dim result2 = Await Client.Workflows.ExtractSwissQrCodeValidatedAsync("rechnung.pdf") +``` + +```powershell +Add-Type -Path "DocumentService.Client.dll" + +# Variante A: byte[] +$pdfBytes = [System.IO.File]::ReadAllBytes("rechnung.pdf") +$result = [DocumentService.Client.Client]::Workflows.ExtractSwissQrCodeValidatedAsync($pdfBytes).GetAwaiter().GetResult() +Write-Host "Betrag: $($result.Bill.Amount) $($result.Bill.Currency)" +Write-Host "Empfaenger:$($result.Bill.Creditor.Name)" + +# Variante B: Dateipfad +$result2 = [DocumentService.Client.Client]::Workflows.ExtractSwissQrCodeValidatedAsync("rechnung.pdf").GetAwaiter().GetResult() +``` + +**Fehlerbehandlung – `throwIfInvalid`:** + +Standardmäßig wirft die Methode eine `InvalidOperationException`, wenn das PDF ungültig ist. Mit `throwIfInvalid: false` wird stattdessen `null` zurückgegeben – geeignet, wenn ungültige Dokumente kein Ausnahmefall sind und ohne try/catch behandelt werden sollen. + +```csharp +// Exception (Standard) – geeignet, wenn ungültige PDFs ein Fehlerfall sind +var result = await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes); + +// Null zurückgeben – geeignet für Batch-Verarbeitung o. Ä. +var result = await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: false); +if (result is null) +{ + Console.WriteLine("Dokument ungültig oder verschlüsselt – übersprungen."); +} +``` + +```vbnet +' Exception (Standard) +Dim result = Await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes) + +' Null zurückgeben +Dim result2 = Await Client.Workflows.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid:=False) +If result2 Is Nothing Then + Console.WriteLine("Dokument ungültig oder verschlüsselt – übersprungen.") +End If +``` + +```powershell +# Exception (Standard) +$result = [DocumentService.Client.Client]::Workflows.ExtractSwissQrCodeValidatedAsync($pdfBytes).GetAwaiter().GetResult() + +# Null zurückgeben ($false = throwIfInvalid:false) +$result2 = [DocumentService.Client.Client]::Workflows.ExtractSwissQrCodeValidatedAsync($pdfBytes, $false, $false).GetAwaiter().GetResult() +if ($null -eq $result2) { + Write-Host "Dokument ungueltig oder verschluesselt – uebersprungen." +} +``` + +> **Signatur:** `ExtractSwissQrCodeValidatedAsync(pdfBytes / Stream / filePath, raw = false, throwIfInvalid = true, ct = default)` +> `raw: true` liefert die Rohtextzeilen des QR-Codes ohne Parsing zurück (siehe [Schweizer QR-Code-Extraktion](#4-schweizer-qr-code-extraktion)). + +--- + ### 1. PDF-Validierung ```csharp @@ -987,6 +1085,7 @@ Sobald die Endpunkte auf dem Server bereitgestellt werden, entfällt das `[Obsol | `Client.Zugferd` | `ExtractZugferdAsResultAsync()` | `POST /api/pdf/zugferd/extract` | ✅ Verfügbar | ZUGFeRD-XML mit Metadaten als Objekt | | `Client.Conversion` | `ConvertToPdfAAsync()` | `POST /api/pdf/conversion/to-pdfa` | ⏳ Geplant | PDF zu PDF/A konvertieren | | `Client.Conversion` | `ConvertFromPdfAAsync()` | `POST /api/pdf/conversion/from-pdfa` | ⏳ Geplant | PDF/A-Einschränkungen aufheben | +| `Client.Workflows` | `ExtractSwissQrCodeValidatedAsync()` | — | ✅ Verfügbar | Validierung + Swiss QR Code Extraktion in einem Schritt | > **⏳ Geplant:** Der Client-Code ist vorhanden und kompiliert fehlerfrei. Ein Aufruf zur Laufzeit wirft jedoch `NotImplementedException`, da der serverseitige Endpunkt noch nicht existiert. Die Methoden sind mit `[Obsolete]` markiert, sodass der Compiler eine Build-Warnung ausgibt.