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.
This commit is contained in:
2026-08-31 03:30:28 +02:00
parent f4d87b42f3
commit f51fde6a23

View File

@@ -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.