Refactor domain models (DomFunktionaer, DomReiter, DomPferd) to align with ZNS conventions: simplify naming, update properties, and enhance parser logic. Adjust related controllers, repository methods, and tests. Update MASTER_ROADMAP with changes to domain models.
This commit is contained in:
+20
-18
@@ -19,10 +19,10 @@ import java.util.zip.ZipInputStream
|
||||
* Domänenobjekte über die jeweiligen Repositories (Upsert-Logik).
|
||||
*
|
||||
* Die Verarbeitungsreihenfolge ist fix:
|
||||
* 1. VEREIN01.DAT → DomVerein (via VereinRepository)
|
||||
* 2. LIZENZ01.DAT → DomReiter (via ReiterRepository)
|
||||
* 3. PFERDE01.DAT → DomPferd (via HorseRepository)
|
||||
* 4. RICHT01.DAT → DomFunktionaer (via FunktionaerRepository)
|
||||
* 1. VEREIN01.DAT → Verein (via VereinRepository)
|
||||
* 2. LIZENZ01.DAT → Reiter (via ReiterRepository)
|
||||
* 3. PFERDE01.DAT → Pferd (via HorseRepository)
|
||||
* 4. RICHT01.DAT → Funktionaer (via FunktionaerRepository)
|
||||
*
|
||||
* Dieser Service hat **keine** Spring-Abhängigkeit und kann daher sowohl
|
||||
* im Backend (REST-Upload) als auch in der Compose Desktop App (Offline-Import)
|
||||
@@ -57,18 +57,19 @@ class ZnsImportService(
|
||||
ZipInputStream(zipInputStream).use { zip ->
|
||||
var entry = zip.nextEntry
|
||||
while (entry != null) {
|
||||
val entryPath = entry.name.uppercase()
|
||||
val fileName = entryPath.substringAfterLast("/")
|
||||
val fileName = entry.name.uppercase().substringAfterLast("/")
|
||||
|
||||
if (fileName in setOf(FILE_VEREIN, FILE_LIZENZ, FILE_PFERDE, FILE_RICHT)) {
|
||||
// Read all bytes from the current entry
|
||||
val bytes = zip.readBytes()
|
||||
// Convert to string using the correct charset and split into lines
|
||||
val content = bytes.toString(CP850)
|
||||
val outputStream = java.io.ByteArrayOutputStream()
|
||||
val buffer = ByteArray(4096)
|
||||
var len: Int
|
||||
while (zip.read(buffer).also { len = it } > 0) {
|
||||
outputStream.write(buffer, 0, len)
|
||||
}
|
||||
val content = outputStream.toString(CP850)
|
||||
val lines = content.split(Regex("\\r?\\n|\\r")).filter { it.isNotBlank() }
|
||||
dateien[fileName] = lines
|
||||
}
|
||||
zip.closeEntry()
|
||||
entry = zip.nextEntry
|
||||
}
|
||||
}
|
||||
@@ -83,6 +84,8 @@ class ZnsImportService(
|
||||
*/
|
||||
suspend fun importiereZip(zipInputStream: InputStream): ZnsImportResult {
|
||||
val dateien = extrahiereDateien(zipInputStream)
|
||||
// println("[DEBUG_LOG] Gefundene Dateien: ${dateien.keys}")
|
||||
// dateien.forEach { (name, lines) -> println("[DEBUG_LOG] Datei $name hat ${lines.size} Zeilen") }
|
||||
|
||||
val fehler = mutableListOf<String>()
|
||||
val warnungen = mutableListOf<String>()
|
||||
@@ -126,13 +129,11 @@ class ZnsImportService(
|
||||
} else {
|
||||
vereinRepository.save(
|
||||
vorhanden.copy(
|
||||
name = verein.name,
|
||||
kurzname = verein.kurzname,
|
||||
vereinName = verein.vereinName,
|
||||
bundesland = verein.bundesland,
|
||||
ort = verein.ort,
|
||||
plz = verein.plz,
|
||||
strasse = verein.strasse,
|
||||
oepsRegionNummer = verein.oepsRegionNummer,
|
||||
istAktiv = verein.istAktiv,
|
||||
datenQuelle = verein.datenQuelle
|
||||
).withUpdatedTimestamp()
|
||||
@@ -207,9 +208,12 @@ class ZnsImportService(
|
||||
val pferd = ZnsLegacyParsers.parsePferd(zeile) ?: return@forEachIndexed
|
||||
if (pferd.pferdeName.isBlank()) return@forEachIndexed
|
||||
|
||||
// Match primarily by satznummer, then by lebensnummer, then by kopfnummer+name
|
||||
// Match primarily by satznummer, then by lebensnummer
|
||||
val vorhanden = pferd.satznummer?.takeIf { it.isNotBlank() }?.let { horseRepository.findBySatznummer(it) }
|
||||
?: pferd.lebensnummer?.takeIf { it.isNotBlank() }?.let { horseRepository.findByLebensnummer(it) }
|
||||
?: (if (pferd.pferdeName.isNotBlank()) horseRepository.findByName(pferd.pferdeName, 100).find {
|
||||
it.geburtsjahr == pferd.geburtsjahr && it.kopfnummer == pferd.kopfnummer
|
||||
} else null)
|
||||
|
||||
if (vorhanden == null) {
|
||||
horseRepository.save(pferd)
|
||||
@@ -253,7 +257,7 @@ class ZnsImportService(
|
||||
zeilen.forEachIndexed { index, zeile ->
|
||||
runCatching {
|
||||
val funktionaer = ZnsLegacyParsers.parseFunktionaer(zeile) ?: return@forEachIndexed
|
||||
val satzID = funktionaer.satzID
|
||||
val satzID = funktionaer.satzId
|
||||
val satzNummer = funktionaer.satzNummer
|
||||
val vorhanden = funktionaerRepository.findBySatz(satzID, satzNummer)
|
||||
if (vorhanden == null) {
|
||||
@@ -262,8 +266,6 @@ class ZnsImportService(
|
||||
} else {
|
||||
funktionaerRepository.save(
|
||||
vorhanden.copy(
|
||||
satzID = satzID,
|
||||
satzNummer = satzNummer,
|
||||
name = funktionaer.name,
|
||||
qualifikationen = funktionaer.qualifikationen,
|
||||
istAktiv = funktionaer.istAktiv,
|
||||
|
||||
+41
-21
@@ -1,9 +1,9 @@
|
||||
package at.mocode.zns.importer
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
@@ -113,29 +113,29 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("VEREIN01.DAT" to vereinZeile())
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer(any()) } returns null
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.vereineImportiert).isEqualTo(1)
|
||||
assertThat(result.vereineAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { vereinRepository.save(any<DomVerein>()) }
|
||||
coVerify(exactly = 1) { vereinRepository.save(any<Verein>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `importiereZip - bestehende Vereine werden aktualisiert`() = runTest {
|
||||
val zip = buildZip("VEREIN01.DAT" to vereinZeile(name = "Neuer Name"))
|
||||
val vorhanden = DomVerein(vereinsNummer = "0001", name = "Alter Name")
|
||||
val vorhanden = Verein(vereinsNummer = "0001", vereinName = "Alter Name")
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer("0001") } returns vorhanden
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.vereineImportiert).isEqualTo(0)
|
||||
assertThat(result.vereineAktualisiert).isEqualTo(1)
|
||||
coVerify(exactly = 1) { vereinRepository.save(match { it.name == "Neuer Name" }) }
|
||||
coVerify(exactly = 1) { vereinRepository.save(match { it.vereinName == "Neuer Name" }) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,14 +143,14 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("LIZENZ01.DAT" to lizenzZeile())
|
||||
|
||||
coEvery { reiterRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<DomReiter>() }
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<Reiter>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.reiterImportiert).isEqualTo(1)
|
||||
assertThat(result.reiterAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { reiterRepository.save(any<DomReiter>()) }
|
||||
coVerify(exactly = 1) { reiterRepository.save(any<Reiter>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,14 +159,34 @@ class ZnsImportServiceTest {
|
||||
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<DomPferd>() }
|
||||
coEvery { horseRepository.findByName(any(), any()) } returns emptyList()
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.pferdeImportiert).isEqualTo(1)
|
||||
assertThat(result.pferdeAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { horseRepository.save(any<DomPferd>()) }
|
||||
coVerify(exactly = 1) { horseRepository.save(any<Pferd>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `importiereZip - Pferde werden ueber Kopfnummer und Geburtsjahr aktualisiert, wenn Satznummer fehlt`() = runTest {
|
||||
// Zeile ohne Satznummer (zu kurz)
|
||||
val zeile = "0001Blitz "
|
||||
val zip = buildZip("PFERDE01.DAT" to zeile)
|
||||
|
||||
val existing = Pferd(pferdeName = "Blitz", kopfnummer = "0001", geschlecht = at.mocode.core.domain.model.PferdeGeschlechtE.UNBEKANNT)
|
||||
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.findByName("Blitz", 100) } returns listOf(existing)
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.pferdeAktualisiert).isEqualTo(1)
|
||||
coVerify(exactly = 1) { horseRepository.save(match { it.pferdeName == "Blitz" && it.pferdId == existing.pferdId }) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,14 +194,14 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("RICHT01.DAT" to funktionaerZeile())
|
||||
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.richterImportiert).isEqualTo(1)
|
||||
assertThat(result.richterAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { funktionaerRepository.save(any<DomFunktionaer>()) }
|
||||
coVerify(exactly = 1) { funktionaerRepository.save(any<Funktionaer>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -192,13 +212,13 @@ class ZnsImportServiceTest {
|
||||
)
|
||||
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.richterImportiert).isEqualTo(4)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 4) { funktionaerRepository.save(any<DomFunktionaer>()) }
|
||||
coVerify(exactly = 4) { funktionaerRepository.save(any<Funktionaer>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -211,14 +231,14 @@ class ZnsImportServiceTest {
|
||||
)
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer(any()) } returns null
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
coEvery { reiterRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<DomReiter>() }
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<Reiter>() }
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<DomPferd>() }
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user