--- type: Roadmap status: IN_PROGRESS owner: Curator last_update: 2026-03-25 --- # Roadmap: ZNS-Importer (MVP) 10. **🏗️ [Lead Architect]** | 5. April 2026 **Kontext:** Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat` existiert nicht. Um den `registration-context` und `actor-context` unter realistischen Bedingungen testen zu können, benötigen wir echte Stammdaten (Reiter, Pferde, Vereine, Funktionäre). Diese Daten werden vom ÖPS (Österreichischer Pferdesportverband) in Form einer `ZNS.zip` bereitgestellt. **Ziel:** Entwicklung eines asynchronen, robusten Importers für die Legacy-ZNS-Daten (`ZNS.zip`), der über die Compose-Desktop-App gesteuert wird und die Daten persistent im Backend (`actor-context`) ablegt. --- ## 1. Spezifikationen & Rahmenbedingungen * **Dateiformat:** Fixed-Width ASCII (Feste Spaltenbreiten, keine Trennzeichen). * **Encoding:** Zwingend **Codepage 850 (CP850)**. (Achtung: Umlaute!). * **Architektur-Muster:** Asynchroner Upload & Processing (Job-Pattern). * **Import-Reihenfolge (Abhängigkeiten beachten!):** 1. `VEREIN01.dat` (Vereine) 2. `LIZENZ01.dat` (Reiter/Lizenzen) 3. `PFERDE01.dat` (Pferde - benötigt Vereins-ID) 4. `RICHT01.dat` (Richter & Parcoursbauer kombiniert in einer Datei) --- ## 2. Phasen & Aufgabenverteilung ### Phase 1: Backend-Infrastruktur & Parsing (👷 Backend Developer) * [x] **API Design:** * `POST /api/v1/import/zns` (Multipart/form-data, nimmt `.zip` oder `.dat` entgegen). * Rückgabe: `202 Accepted` mit einer `JobId` (UUID). * `GET /api/v1/import/zns/{jobId}/status` (Gibt aktuellen Fortschritt und Statusmeldungen zurück). * Implementiert in `backend:services:zns-import:zns-import-service` (`ZnsImportController`). ✅ * [x] **Job-Management:** * Thread-sichere In-Memory-Registry (`ImportJobRegistry`, `ConcurrentHashMap`) implementiert. * Status-Enum: `AUSSTEHEND`, `ENTPACKEN`, `LADE_VEREINE`, `LADE_REITER`, `LADE_PFERDE`, `LADE_RICHTER`, `ABGESCHLOSSEN`, `FEHLER`. ✅ * [x] **Unzip-Service:** * ZIP-Entpackung in-memory implementiert (`ZnsImportService`). * [x] **Legacy-Parser (CP850 Fixed-Width):** * `ZnsLegacyParsers` in `core:zns-parser` (KMP-Modul) implementiert. * Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und Parcoursbauer ('Y'). ✅ ### Phase 2: Domain-Mapping & Persistenz (👷 Backend Developer) * [x] **Mapper-Logik:** * `DomVerein`, `DomReiter`, `DomPferd`, `DomFunktionaer` vollständig gemappt. * *Sonderfälle umgesetzt:* * `PFERDE01.dat`: Ausländische Systemnummern werden ignoriert. ✅ * `LIZENZ01.dat`: Sperrlisten-Flag (`S`) korrekt auf `DomReiter` gemappt. ✅ * [x] **Upsert-Strategie (DB):** * `ZnsImportService` implementiert find + save Logik (Upsert). 7 Unit-Tests grün. * Fehler pro Zeile werden gesammelt (kein Abbruch bei Einzelfehlern). `ZnsImportResult` mit Zählern & Fehlerlisten. ### Phase 3: Frontend-Integration (🎨 Frontend Expert) * [x] **UI-Komponenten (Compose Desktop):** * `StammdatenImportScreen` in `meldestelle-desktop` erstellt. ✅ * Nativer File-Picker (`JFileChooser`, nur `.zip`) integriert. ✅ * `AppScreen.StammdatenImport` + Nav-Rail-Eintrag "Stammdaten-Import" hinzugefügt. ✅ * [x] **Netzwerk & State-Management (KMP):** * `ZnsImportViewModel` mit Ktor Multipart-Upload (`POST /api/v1/import/zns`). ✅ * Polling-Mechanismus (alle 2 Sekunden, `GET /api/v1/import/zns/{jobId}/status`). ✅ * `ZnsImportViewModel` via Koin `viewModel { }` in `desktopModule` registriert. ✅ * [x] **User Feedback:** * `LinearProgressIndicator` mit Live-Prozent + `progressDetail`-Text. ✅ * `StatusChip` für alle Job-Zustände (AUSSTEHEND → ABGESCHLOSSEN/FEHLER). ✅ * Fehler-Banner + scrollbare Fehler-Liste (max. 50 Einträge). ✅ ### Phase 4: Testing & QA (🧐 QA Specialist) * [ ] **Test-Datensatz prüfen:** * Einlesen der `docs/OePS/ZNS.zip` und Überprüfung der Umlaute (CP850 Encoding Test). * [ ] **Abhängigkeits-Test:** * Sicherstellen, dass Pferde korrekt ihren Vereinen zugeordnet werden. * [ ] **Edge-Cases:** * Upload einer fehlerhaften Zip-Datei. * Abbruch des Uploads/Imports. --- ## 3. Offene Fragen / Risiken * Werden die Legacy-Daten in der Datenbank (PostgreSQL) mit UUIDs oder mit den ZNS-Satznummern als Primary Keys abgelegt? * *Architektur-Beschluss:* Wir sollten interne UUIDs als Primary Keys verwenden und die ZNS-Nummern als eindeutige Business-Keys (`UNIQUE CONSTRAINT`) ablegen. * Wie gehen wir mit gelöschten Datensätzen aus dem ZNS um? * *Vorerst:* Der ZNS-Import ist ein "Add/Update"-Only Vorgang. Löschungen müssen manuell oder in einer späteren Phase synchronisiert werden.