Accounting A-4 (PDF): neutrale Abrechnung als PDF via PDFsharp/MigraDoc (MIT)

Vervollstaendigt den Export (CSV war A-2) um PDF - laenderneutral, KEINE steuerliche Einordnung.
PDFsharp/MigraDoc-GDI 6.2.4 (echte MIT ohne Umsatzschwelle; GDI-Variante nutzt System-Fonts auf
Windows/WinForms; keine NU1701-Transitiven - bewusst NICHT QuestPDF).

- PdfExporter (Logic): Kopf (Konto/Zeitraum/Waehrung/Datum) + Aggregat-Tabelle + Monatsvergleich +
  Transaktionsliste + Methodik-/Nachweis-Seite (append-only-Quelle, Cash-Basis, 'keine Steuerberatung',
  SHA-256-Daten-Hash fuer Reproduzierbarkeit). Betraege in Anzeige-Waehrung (Faktor uebergeben ->
  Services-unabhaengig). Landscape.
- UI: Button 'PDF-Export' (via Designer) neben CSV; Export via SaveFileDialog in gewaehlter Waehrung.
- Test: PdfExporter erzeugt valide PDF-Bytes (%PDF-Signatur) headless -> MigraDoc-Rendering verifiziert.

Build 0 Fehler, 386 Tests gruen, --smoke-ui alle 6 Views gruen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-20 15:10:52 +02:00
co-authored by Claude Opus 4.8
parent 42a599a3a3
commit ca0d4ceed0
5 changed files with 233 additions and 1 deletions
@@ -127,5 +127,25 @@ namespace PolyTrader.Tests
Assert.Contains("Endsaldo,135", csv);
Assert.Contains("Netto-Handelsergebnis (Cash),35", csv);
}
// ---------------- PdfExporter (MigraDoc-Rendering headless) ----------------
[Fact]
public void Pdf_render_produces_valid_pdf_bytes()
{
var s = new PeriodStatement(1, Jul, Jul, 100m, 135m, 200m, 50m, 230m, 0m, 5m, 2m, 35m, 2, 1);
var entries = new List<LedgerEntry>
{
new() { AccountId = 1, EventType = LedgerEventType.TradeSell, Timestamp = Jul,
MarketSlug = "market-x", Side = "SELL", Size = 10m, PriceUsdc = 0.5m,
GrossUsdc = 130m, FeeUsdc = 1m, NetUsdc = 129m, TxHash = "0xabc" }
};
byte[] pdf = PdfExporter.Render(s, new[] { s }, entries, "USDC", 1.0m, "Native Buchungswährung.");
Assert.True(pdf.Length > 500);
// PDF-Signatur %PDF-
Assert.Equal(new byte[] { 0x25, 0x50, 0x44, 0x46 }, pdf.Take(4).ToArray());
}
}
}