Remove deprecated ZnsLegacyParsersTest.kt, synchronize database schema with Exposed domain models (migration V010), add license-related fields to Reiter, integrate updated LicenseMatrixService fallback logic, improve ZnsImportService with file archiving, and add ZNS testing runbook.
This commit is contained in:
+9
@@ -1,5 +1,6 @@
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.LicenseMatrixEntry
|
||||
@@ -42,6 +43,14 @@ class LicenseMatrixServiceImpl : LicenseMatrixService {
|
||||
// Suche passenden Eintrag in der Matrix für (Sparte, Lizenzklasse)
|
||||
val entry = matrix.find { it.sparte == sparte && it.lizenzKlasse == reiter.lizenzKlasse }
|
||||
?: matrix.find { it.sparte == SparteE.DRESSUR && sparte == SparteE.DRESSUR && it.lizenzKlasse == reiter.lizenzKlasse } // Fallback/Spezial
|
||||
?: if (reiter.lizenzKlasse == ReiterLizenzKlasseE.R1 ||
|
||||
reiter.lizenzKlasse == ReiterLizenzKlasseE.R2 ||
|
||||
reiter.lizenzKlasse == ReiterLizenzKlasseE.R3 ||
|
||||
reiter.lizenzKlasse == ReiterLizenzKlasseE.R4) {
|
||||
// Fallback für Dressur, wenn man eine Springlizenz hat (R1 gilt oft auch als RD1 etc. in manchen Kontexten,
|
||||
// aber hier schauen wir primär ob die Matrix einen generischen Eintrag hat)
|
||||
matrix.find { it.sparte == sparte && it.lizenzKlasse == ReiterLizenzKlasseE.LIZENZFREI }
|
||||
} else null
|
||||
|
||||
return entry?.maxTurnierklasseCode
|
||||
}
|
||||
|
||||
+2
@@ -95,6 +95,7 @@ class LicenseMatrixServiceTest {
|
||||
satznummer = "1",
|
||||
nachname = "R1",
|
||||
vorname = "Reiter",
|
||||
reiterLizenz = "R1",
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
|
||||
@@ -114,6 +115,7 @@ class LicenseMatrixServiceTest {
|
||||
satznummer = "2",
|
||||
nachname = "RD1",
|
||||
vorname = "Reiter",
|
||||
reiterLizenz = "RD1",
|
||||
lizenzKlasse = ReiterLizenzKlasseE.RD1
|
||||
)
|
||||
|
||||
|
||||
-1
@@ -7,7 +7,6 @@ import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import at.mocode.masterdata.infrastructure.persistence.LicenseTable.lizenzKlasse
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.eq
|
||||
import org.jetbrains.exposed.v1.jdbc.*
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ object ReiterTable : Table("reiter") {
|
||||
val feiId = varchar("fei_id", 20).nullable()
|
||||
val sperrListe = varchar("sperr_liste", 50).nullable()
|
||||
val lizenzInfo = varchar("lizenz_info", 100).nullable()
|
||||
val lizenzKlasse = varchar("lizenz_klasse", 20).default("LIZENZFREI")
|
||||
|
||||
// === ZNS.zip LITENZ01.DAT === ENDE ===
|
||||
|
||||
|
||||
+1
@@ -98,6 +98,7 @@ class RegulationSeedVerificationTest {
|
||||
satznummer = "123456",
|
||||
nachname = "Müller",
|
||||
vorname = "Hans",
|
||||
reiterLizenz = "R1",
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
-- V010: Synchronize Database Schema with Exposed Domain Models
|
||||
-- Harmonisiert die Spaltennamen und Typen mit den aktuellen Kotlin-Definitionen.
|
||||
|
||||
-- 1. Tabelle VEREIN anpassen
|
||||
ALTER TABLE verein RENAME COLUMN name TO verein_name;
|
||||
ALTER TABLE verein DROP COLUMN IF EXISTS kurzname;
|
||||
ALTER TABLE verein DROP COLUMN IF EXISTS oeps_region_nummer;
|
||||
ALTER TABLE verein ADD COLUMN IF NOT EXISTS person_id UUID;
|
||||
ALTER TABLE verein ADD COLUMN IF NOT EXISTS image_url VARCHAR(255);
|
||||
ALTER TABLE verein ADD COLUMN IF NOT EXISTS hausnummer VARCHAR(10);
|
||||
|
||||
-- 2. Tabelle REITER anpassen
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS bundesland_nummer INTEGER;
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS reiter_lizenz VARCHAR(20);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS startkarte VARCHAR(20);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS fahr_lizenz VARCHAR(20);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS altersklasse_jg_jr_u25 VARCHAR(10);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS altersklasse_y VARCHAR(10);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS mitglieds_nummer INTEGER;
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS telefon_nummer VARCHAR(50);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS kader VARCHAR(50);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS last_pay_year INTEGER;
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS geschlecht VARCHAR(10);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS sperr_liste VARCHAR(50);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS lizenz_info VARCHAR(100);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS lizenz_klasse VARCHAR(20) DEFAULT 'LIZENZFREI';
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS image_url VARCHAR(255);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS website VARCHAR(255);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS strasse VARCHAR(200);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS hausnummer VARCHAR(10);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS plz VARCHAR(10);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS ort VARCHAR(100);
|
||||
ALTER TABLE reiter ADD COLUMN IF NOT EXISTS bundesland VARCHAR(100);
|
||||
|
||||
-- 3. Tabelle HORSE anpassen (in Exposed "HorseTable" aber in SQL "horse")
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS kopfnummer VARCHAR(4);
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS geburtsjahr INTEGER;
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS abstammung VARCHAR(100);
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS verein_nummer INTEGER;
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS last_pay_year INTEGER;
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS vater VARCHAR(200);
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS fei_pass VARCHAR(50);
|
||||
ALTER TABLE horse ADD COLUMN IF NOT EXISTS satznummer VARCHAR(10);
|
||||
-- Aufräumen von Feldern die nicht im Exposed Model sind (aus V006)
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS geburtsdatum;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS rasse;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS besitzer_id;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS zuechter_name;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS zuchtbuch_nummer;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS chip_nummer;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS pass_nummer;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS oeps_nummer;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS fei_nummer;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS vater_name;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS mutter_name;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS mutter_vater_name;
|
||||
ALTER TABLE horse DROP COLUMN IF EXISTS stockmass;
|
||||
|
||||
-- 4. Tabelle FUNKTIONAER anpassen
|
||||
ALTER TABLE funktionaer DROP COLUMN IF EXISTS richter_nummer;
|
||||
ALTER TABLE funktionaer DROP COLUMN IF EXISTS vorname;
|
||||
ALTER TABLE funktionaer DROP COLUMN IF EXISTS nachname;
|
||||
ALTER TABLE funktionaer DROP COLUMN IF EXISTS geburtsdatum;
|
||||
ALTER TABLE funktionaer DROP COLUMN IF EXISTS vereins_nummer;
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS person_id UUID;
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS satz_id VARCHAR(1);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS satz_nummer INTEGER;
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS name VARCHAR(200);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS image_url VARCHAR(255);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS website VARCHAR(255);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS strasse VARCHAR(200);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS hausnummer VARCHAR(10);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS plz VARCHAR(10);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS ort VARCHAR(100);
|
||||
ALTER TABLE funktionaer ADD COLUMN IF NOT EXISTS bundesland VARCHAR(100);
|
||||
|
||||
-- 5. Qualifikations-Tabelle für Funktionäre
|
||||
CREATE TABLE IF NOT EXISTS funktionaer_qualifikation (
|
||||
funktionaer_id UUID NOT NULL REFERENCES funktionaer(funktionaer_id),
|
||||
qualifikation VARCHAR(20) NOT NULL,
|
||||
PRIMARY KEY (funktionaer_id, qualifikation)
|
||||
);
|
||||
|
||||
-- Indizes (Exposed-Style)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_horse_satznummer ON horse (satznummer);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_reiter_satznummer ON reiter (satznummer);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_funktionaer_satz ON funktionaer (satz_id, satz_nummer);
|
||||
+18
-1
@@ -1,7 +1,13 @@
|
||||
package at.mocode.zns.import.service
|
||||
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import at.mocode.masterdata.domain.repository.VereinRepository
|
||||
import at.mocode.zns.importer.ZnsImportService
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.ComponentScan
|
||||
|
||||
@SpringBootApplication
|
||||
@@ -11,7 +17,18 @@ import org.springframework.context.annotation.ComponentScan
|
||||
"at.mocode.masterdata.infrastructure"
|
||||
]
|
||||
)
|
||||
class ZnsImportServiceApplication
|
||||
class ZnsImportServiceApplication {
|
||||
|
||||
@Bean
|
||||
fun znsImportService(
|
||||
vereinRepository: VereinRepository,
|
||||
reiterRepository: ReiterRepository,
|
||||
horseRepository: HorseRepository,
|
||||
funktionaerRepository: FunktionaerRepository
|
||||
): ZnsImportService {
|
||||
return ZnsImportService(vereinRepository, reiterRepository, horseRepository, funktionaerRepository)
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
runApplication<ZnsImportServiceApplication>(*args)
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
enum class ImportJobStatus { AUSSTEHEND, ENTPACKEN, LADE_VEREINE, LADE_REITER, LADE_PFERDE, LADE_RICHTER, ABGESCHLOSSEN, FEHLER }
|
||||
enum class ImportJobStatus { AUSSTEHEND, ENTPACKEN, VERARBEITUNG, ABGESCHLOSSEN, FEHLER }
|
||||
|
||||
data class ImportJob(
|
||||
val jobId: String,
|
||||
|
||||
+27
-38
@@ -1,23 +1,21 @@
|
||||
package at.mocode.zns.import.service.job
|
||||
|
||||
import at.mocode.masterdata.domain.repository.VereinRepository
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import at.mocode.zns.importer.ZnsImportService
|
||||
import at.mocode.zns.importer.ZnsImportResult
|
||||
import at.mocode.zns.importer.ZnsImportService
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Service
|
||||
import java.io.File
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Service
|
||||
class ZnsImportOrchestrator(
|
||||
private val vereinRepository: VereinRepository,
|
||||
private val reiterRepository: ReiterRepository,
|
||||
private val horseRepository: HorseRepository,
|
||||
private val funktionaerRepository: FunktionaerRepository,
|
||||
private val jobRegistry: ImportJobRegistry
|
||||
private val service: ZnsImportService,
|
||||
private val jobRegistry: ImportJobRegistry,
|
||||
@Value("\${app.zns.archive-path}") private val archivePath: String
|
||||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
@@ -26,38 +24,15 @@ class ZnsImportOrchestrator(
|
||||
runCatching {
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.ENTPACKEN, "Entpacke ZIP-Datei...", 5)
|
||||
|
||||
val service = ZnsImportService(vereinRepository, reiterRepository, horseRepository, funktionaerRepository)
|
||||
// Archivierung
|
||||
archiviereZip(zipBytes)
|
||||
|
||||
val dateien = service.extrahiereDateien(zipBytes.inputStream())
|
||||
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.LADE_VEREINE, "Lade Vereine...", 20)
|
||||
val vereineResult = service.importiereVereine(dateien["VEREIN01.DAT"] ?: emptyList(), mutableListOf())
|
||||
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.LADE_REITER, "Lade Reiter...", 40)
|
||||
val reiterResult = service.importiereReiter(dateien["LIZENZ01.DAT"] ?: emptyList(), mutableListOf(), mutableListOf())
|
||||
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.LADE_PFERDE, "Lade Pferde...", 60)
|
||||
val pferdeResult = service.importierePferde(dateien["PFERDE01.DAT"] ?: emptyList(), mutableListOf())
|
||||
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.LADE_RICHTER, "Lade Funktionäre...", 80)
|
||||
val richterResult = service.importiereFunktionaere(dateien["RICHT01.DAT"] ?: emptyList(), mutableListOf(), mutableListOf())
|
||||
|
||||
val result = ZnsImportResult(
|
||||
vereineImportiert = vereineResult.first,
|
||||
vereineAktualisiert = vereineResult.second,
|
||||
reiterImportiert = reiterResult.first,
|
||||
reiterAktualisiert = reiterResult.second,
|
||||
pferdeImportiert = pferdeResult.first,
|
||||
pferdeAktualisiert = pferdeResult.second,
|
||||
richterImportiert = richterResult.first,
|
||||
richterAktualisiert = richterResult.second
|
||||
)
|
||||
jobRegistry.aktualisiereStatus(jobId, ImportJobStatus.VERARBEITUNG, "Verarbeite ZNS-Daten...", 20)
|
||||
val result = service.importiereZip(zipBytes.inputStream())
|
||||
|
||||
jobRegistry.aktualisiereStatus(
|
||||
jobId, ImportJobStatus.ABGESCHLOSSEN,
|
||||
"Import abgeschlossen: ${result.vereineImportiert} Vereine, " +
|
||||
"${result.reiterImportiert} Reiter, ${result.pferdeImportiert} Pferde, " +
|
||||
"${result.richterImportiert} Richter importiert.", 100
|
||||
result.zusammenfassung(), 100
|
||||
)
|
||||
|
||||
jobRegistry.findeJob(jobId)?.let { job ->
|
||||
@@ -70,4 +45,18 @@ class ZnsImportOrchestrator(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun archiviereZip(bytes: ByteArray) {
|
||||
try {
|
||||
val dir = File(archivePath)
|
||||
if (!dir.exists()) dir.mkdirs()
|
||||
|
||||
val timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
|
||||
val archiveFile = File(dir, "zns_import_$timestamp.zip")
|
||||
archiveFile.writeBytes(bytes)
|
||||
} catch (e: Exception) {
|
||||
// Archivierung schlägt fehl -> Loggen aber Import nicht abbrechen
|
||||
println("[WARN] Archivierung der ZNS-Datei fehlgeschlagen: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,5 @@ management:
|
||||
|
||||
app:
|
||||
service-name: ${spring.application.name}
|
||||
zns:
|
||||
archive-path: ${ZNS_ARCHIVE_PATH:/data/zns/archive}
|
||||
|
||||
Reference in New Issue
Block a user