Refactor master data infrastructure to streamline Reiter and Bundesland relationships, add V012 migration, harmonize domain models, implement repository methods for enhanced ZNS import logic, and update associated tests.
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.domain.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Domain-Modell für Bundesland.
|
||||
*/
|
||||
@Serializable
|
||||
data class Bundesland(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val id: Uuid,
|
||||
val bundeslandNr: Int,
|
||||
val bezeichnung: String,
|
||||
val wappenUrl: String? = null
|
||||
)
|
||||
+1
@@ -35,6 +35,7 @@ data class BundeslandDefinition(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
var landId: Uuid, // FK zu LandDefinition.landId
|
||||
|
||||
var bundeslandNr: Int? = null,
|
||||
var oepsCode: String?, // z. B. "01", "02", ... für Österreich; eindeutig pro landId = Österreich
|
||||
var iso3166_2_Code: String?, // z. B. "AT-1", "DE-BY"; Eindeutig global oder pro Land?
|
||||
var name: String, // z. B. "Niederösterreich", "Bayern"
|
||||
|
||||
+35
-13
@@ -78,6 +78,16 @@ data class Reiter(
|
||||
// Alphanumerisch (3)
|
||||
var nation: String? = null,
|
||||
|
||||
// Relationen zu Masterdaten
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
var vereinId: Uuid? = null,
|
||||
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
var bundeslandId: Uuid? = null,
|
||||
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
var nationId: Uuid? = null,
|
||||
|
||||
// Alphanumerisch (4) Keine Lizenz: BLANK
|
||||
var reiterLizenz: String? = null,
|
||||
|
||||
@@ -126,19 +136,6 @@ data class Reiter(
|
||||
|
||||
// === ZNS.zip LIZENZ01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
var imageUrl: String? = null,
|
||||
var email: String? = null,
|
||||
var telefon: String? = null,
|
||||
var website: String? = null,
|
||||
|
||||
// Adresse
|
||||
var strasse: String? = null,
|
||||
var hausnummer: String? = null,
|
||||
var plz: String? = null,
|
||||
var ort: String? = null,
|
||||
var bundesland: String? = null,
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv: Boolean = true,
|
||||
var bemerkungen: String? = null,
|
||||
@@ -183,6 +180,27 @@ data class Reiter(
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the 8-digit membership number.
|
||||
* Format: [B][VVV][MMMM]
|
||||
* B: Bundesland (1 digit)
|
||||
* VVV: Verein (3 digits)
|
||||
* MMMM: Member (4 digits)
|
||||
*/
|
||||
fun validateMitgliedsNummer(): Boolean {
|
||||
val nrStr = mitgliedsNummer?.toString()?.padStart(8, '0') ?: return false
|
||||
if (nrStr.length != 8) return false
|
||||
|
||||
val b = nrStr.substring(0, 1).toInt()
|
||||
// Validation against bundeslandNummer if available
|
||||
if (bundeslandNummer != null && b != (bundeslandNummer!! % 10)) {
|
||||
// ZNS bundeslandNummer is 01-09, while membership first digit is 1-9
|
||||
// This might need refinement depending on how "00" (Unbekannt) is handled in membership numbers.
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the rider for competition entry.
|
||||
* Returns a list of warning messages (never hard errors – TBA has final say).
|
||||
@@ -198,6 +216,10 @@ data class Reiter(
|
||||
warnings.add("Reiter ${getDisplayName()} hat keine aktive Startkarte für das aktuelle Jahr")
|
||||
}
|
||||
|
||||
if (!validateMitgliedsNummer()) {
|
||||
warnings.add("Reiter ${getDisplayName()} hat eine ungültige Mitgliedsnummer")
|
||||
}
|
||||
|
||||
return warnings
|
||||
}
|
||||
|
||||
|
||||
+5
-46
@@ -6,112 +6,71 @@ import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Repository interface for BundeslandDefinition (Federal State) domain operations.
|
||||
*
|
||||
* This interface defines the contract for federal state data access operations
|
||||
* without depending on specific implementation details (database, etc.).
|
||||
* Following the hexagonal architecture pattern, this interface belongs
|
||||
* to the domain layer and will be implemented in the infrastructure layer.
|
||||
*/
|
||||
interface BundeslandRepository {
|
||||
|
||||
/**
|
||||
* ZNS-Spezifisch: Sucht ein Bundesland anhand seiner Nummer (01-09).
|
||||
*/
|
||||
suspend fun findByNr(nr: Int): at.mocode.masterdata.domain.model.BundeslandDefinition?
|
||||
|
||||
/**
|
||||
* Finds a federal state by its unique ID.
|
||||
*
|
||||
* @param id The unique identifier of the federal state
|
||||
* @return The federal state if found, null otherwise
|
||||
*/
|
||||
suspend fun findById(id: Uuid): BundeslandDefinition?
|
||||
|
||||
/**
|
||||
* Finds a federal state by its OEPS code.
|
||||
*
|
||||
* @param oepsCode The OEPS code (e.g., "01", "02")
|
||||
* @param landId The country ID to search within
|
||||
* @return The federal state if found, null otherwise
|
||||
*/
|
||||
suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition?
|
||||
|
||||
/**
|
||||
* Finds a federal state by its ISO 3166-2 code.
|
||||
*
|
||||
* @param iso3166_2_Code The ISO 3166-2 code (e.g., "AT-1", "DE-BY")
|
||||
* @return The federal state if found, null otherwise
|
||||
*/
|
||||
suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition?
|
||||
|
||||
/**
|
||||
* Finds all federal states for a specific country.
|
||||
*
|
||||
* @param landId The country ID
|
||||
* @param activeOnly Whether to return only active federal states
|
||||
* @param orderBySortierung Whether to order by sortierReihenfolge field
|
||||
* @return List of federal states for the country
|
||||
*/
|
||||
suspend fun findByCountry(landId: Uuid, activeOnly: Boolean = true, orderBySortierung: Boolean = true): List<BundeslandDefinition>
|
||||
|
||||
/**
|
||||
* Finds federal states by name (partial match).
|
||||
*
|
||||
* @param searchTerm The search term to match against federal state names
|
||||
* @param landId Optional country ID to limit search
|
||||
* @param limit Maximum number of results to return
|
||||
* @return List of matching federal states
|
||||
*/
|
||||
suspend fun findByName(searchTerm: String, landId: Uuid? = null, limit: Int = 50): List<BundeslandDefinition>
|
||||
|
||||
/**
|
||||
* Finds all active federal states.
|
||||
*
|
||||
* @param orderBySortierung Whether to order by sortierReihenfolge field
|
||||
* @return List of active federal states
|
||||
*/
|
||||
suspend fun findAllActive(orderBySortierung: Boolean = true): List<BundeslandDefinition>
|
||||
|
||||
/**
|
||||
* Saves a federal state (create or update).
|
||||
*
|
||||
* @param bundesland The federal state to save
|
||||
* @return The saved federal state with updated timestamps
|
||||
*/
|
||||
suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition
|
||||
|
||||
/**
|
||||
* Upsert basierend auf dem natürlichen Schlüssel (landId + kuerzel).
|
||||
* Existiert bereits ein Datensatz mit gleicher Kombination, wird er aktualisiert,
|
||||
* ansonsten wird ein neuer Datensatz eingefügt.
|
||||
*/
|
||||
suspend fun upsertByLandIdAndKuerzel(bundesland: BundeslandDefinition): BundeslandDefinition
|
||||
|
||||
/**
|
||||
* Deletes a federal state by ID.
|
||||
*
|
||||
* @param id The unique identifier of the federal state to delete
|
||||
* @return true if the federal state was deleted, false if not found
|
||||
*/
|
||||
suspend fun delete(id: Uuid): Boolean
|
||||
|
||||
/**
|
||||
* Checks if a federal state with the given OEPS code exists for a country.
|
||||
*
|
||||
* @param oepsCode The OEPS code to check
|
||||
* @param landId The country ID
|
||||
* @return true if a federal state with this code exists, false otherwise
|
||||
*/
|
||||
suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean
|
||||
|
||||
/**
|
||||
* Checks if a federal state with the given ISO 3166-2 code exists.
|
||||
*
|
||||
* @param iso3166_2_Code The ISO 3166-2 code to check
|
||||
* @return true if a federal state with this code exists, false otherwise
|
||||
*/
|
||||
suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean
|
||||
|
||||
/**
|
||||
* Counts the total number of active federal states for a country.
|
||||
*
|
||||
* @param landId The country ID
|
||||
* @return The total count of active federal states
|
||||
*/
|
||||
suspend fun countActiveByCountry(landId: Uuid): Long
|
||||
}
|
||||
|
||||
+5
@@ -23,6 +23,11 @@ interface VereinRepository {
|
||||
*/
|
||||
suspend fun findByVereinsNummer(vereinsNummer: String): Verein?
|
||||
|
||||
/**
|
||||
* Sucht einen Verein anhand seines exakten Namens.
|
||||
*/
|
||||
suspend fun findByExactName(vereinName: String): Verein?
|
||||
|
||||
/**
|
||||
* Sucht Vereine anhand des Namens (Teilübereinstimmung).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user