chore: remove deprecated horses, clubs, officials, and persons services

- Deleted obsolete modules related to horses, clubs, officials, and persons services, including their configurations, build files, and database provisioning scripts.
- Cleaned up associated references in the project structure (e.g., `settings.gradle.kts`).
- Removed unused database tables and Spring beans related to these domains.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-03-28 16:50:49 +01:00
parent 2cb3f0b125
commit c806660685
181 changed files with 4121 additions and 8694 deletions
@@ -1,13 +1,12 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.SparteE // Optional, falls Altersklassen stark spartenspezifisch sind
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.model.SparteE
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Definiert eine spezifische Altersklasse für Teilnehmer (Reiter, Fahrer, Voltigierer)
@@ -52,8 +51,8 @@ data class AltersklasseDefinition(
var istAktiv: Boolean = true,
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
@Serializable(with = InstantSerializer::class)
val createdAt: Instant,
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant
)
@@ -1,12 +1,11 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Definiert ein Bundesland oder eine vergleichbare subnationale Verwaltungseinheit.
@@ -44,8 +43,8 @@ data class BundeslandDefinition(
var istAktiv: Boolean = true,
var sortierReihenfolge: Int? = null,
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
@Serializable(with = InstantSerializer::class)
val createdAt: Instant,
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant
)
@@ -0,0 +1,126 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.domain.model.FunktionaerRolleE
import at.mocode.core.domain.model.RichterQualifikationE
import at.mocode.core.domain.model.SparteE
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
import kotlin.time.Clock
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Domain-Modell für einen Funktionär im actor-context.
*
* Repräsentiert eine Person mit einer definierten Rolle bei Turnieren (Richter, TBA,
* Parcoursbauer, etc.). Die Qualifikation wird gegen `RICHT01.DAT` aus dem ZNS geprüft.
*
* Aggregate Root des `officials`-Bounded Context.
*
* @property funktionaerId Eindeutige interne ID (UUID).
* @property richterNummer ÖPS-Funktionärsnummer aus ZNS (RICHT01.dat), 6-stellig.
* @property vorname Vorname der Person.
* @property nachname Nachname der Person.
* @property geburtsdatum Geburtsdatum (optional, für Altersklassen-Prüfung).
* @property rollen Menge der Rollen, die diese Person ausüben darf (TBA, Richter, ...).
* @property richterQualifikation Qualifikationsstufe als Richter (GA, G1G3, International).
* @property qualifiziertFuerSparten Sparten, für die eine Richter-Qualifikation vorliegt.
* @property email E-Mail-Adresse für Kommunikation.
* @property telefon Telefonnummer.
* @property vereinsNummer Vereinsnummer des Heimvereins (Referenz auf DomVerein).
* @property istAktiv Ob der Funktionär aktuell aktiv/einsatzbereit ist.
* @property bemerkungen Interne Notizen.
* @property datenQuelle Herkunft des Datensatzes (ZNS-Import oder manuell).
* @property createdAt Erstellungszeitpunkt.
* @property updatedAt Letzter Änderungszeitpunkt.
*/
@Serializable
data class DomFunktionaer(
@Serializable(with = UuidSerializer::class)
val funktionaerId: Uuid = Uuid.random(),
// Identifikation
val richterNummer: String? = null,
// Persönliche Daten
var vorname: String,
var nachname: String,
var geburtsdatum: LocalDate? = null,
// Qualifikation & Rollen
var rollen: Set<FunktionaerRolleE> = emptySet(),
var richterQualifikation: RichterQualifikationE? = null,
var qualifiziertFuerSparten: Set<SparteE> = emptySet(),
// Kontakt
var email: String? = null,
var telefon: String? = null,
// Vereinszugehörigkeit
var vereinsNummer: String? = null,
// Status & Verwaltung
var istAktiv: Boolean = true,
var bemerkungen: String? = null,
var datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
// Audit
@Serializable(with = InstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
) {
/**
* Gibt den vollständigen Anzeigenamen zurück.
*/
fun getDisplayName(): String = "$vorname $nachname"
/**
* Gibt den Anzeigenamen mit Funktionärsnummer zurück (falls vorhanden).
*/
fun getDisplayNameWithNummer(): String =
richterNummer?.let { "${getDisplayName()} ($it)" } ?: getDisplayName()
/**
* Prüft, ob der Funktionär als Richter für eine bestimmte Sparte qualifiziert ist.
*/
fun istRichterFuerSparte(sparte: SparteE): Boolean =
rollen.contains(FunktionaerRolleE.RICHTER) && qualifiziertFuerSparten.contains(sparte)
/**
* Prüft, ob der Funktionär die Rolle TBA ausüben darf.
*/
fun istTba(): Boolean = rollen.contains(FunktionaerRolleE.TBA)
/**
* Validiert die Pflichtfelder für den Turniereinsatz.
* Gibt eine Liste von Warnungen zurück (kein harter Fehler Override-Event möglich).
*/
fun validateFuerTurniereinsatz(rolle: FunktionaerRolleE, sparte: SparteE? = null): List<String> {
val warnings = mutableListOf<String>()
if (!istAktiv) {
warnings.add("Funktionär ${getDisplayName()} ist nicht aktiv.")
}
if (!rollen.contains(rolle)) {
warnings.add("Funktionär ${getDisplayName()} hat keine Qualifikation für Rolle $rolle.")
}
if (rolle == FunktionaerRolleE.RICHTER && sparte != null && !istRichterFuerSparte(sparte)) {
warnings.add("Funktionär ${getDisplayName()} ist nicht als Richter für Sparte $sparte qualifiziert.")
}
return warnings
}
/**
* Erstellt eine Kopie mit aktualisiertem Zeitstempel.
*/
fun withUpdatedTimestamp(): DomFunktionaer = this.copy(updatedAt = Clock.System.now())
}
@@ -0,0 +1,175 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.domain.model.PferdeGeschlechtE
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlinx.datetime.LocalDate
import kotlinx.datetime.number
import kotlinx.datetime.todayIn
import kotlinx.serialization.Serializable
import kotlin.time.Clock
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Domain model representing a horse in the registry system.
*
* This entity contains all essential information about a horse including
* identification, ownership, breeding information, and administrative data.
* It serves as the core aggregate root for the horse-registry bounded context.
*
* @property pferdId Unique internal identifier for this horse (UUID).
* @property pferdeName Name of the horse.
* @property geschlecht Gender of the horse (Hengst, Stute, Wallach).
* @property geburtsdatum Birthdate of the horse.
* @property rasse Breed of the horse.
* @property farbe Color/coat of the horse.
* @property besitzerId ID of the current owner (Person from member-management context).
* @property verantwortlichePersonId ID of the responsible person (trainer, rider, etc.).
* @property zuechterName Name of the breeder.
* @property zuchtbuchNummer Studbook number if registered.
* @property lebensnummer Life number (unique identification number).
* @property chipNummer Microchip number for identification.
* @property passNummer Passport number.
* @property oepsNummer OEPS (Austrian Equestrian Federation) number.
* @property feiNummer FEI (International Equestrian Federation) number.
* @property vaterName Name of the sire (father).
* @property mutterName Name of the dam (mother).
* @property mutterVaterName Name of the maternal grandsire.
* @property stockmass Height of the horse in cm.
* @property istAktiv Whether the horse is currently active in the system.
* @property bemerkungen Additional notes or comments.
* @property datenQuelle Source of the data (manual entry, import, etc.).
* @property createdAt Timestamp when this record was created.
* @property updatedAt Timestamp when this record was last updated.
*/
@Serializable
data class DomPferd(
@Serializable(with = UuidSerializer::class)
val pferdId: Uuid = Uuid.random(),
// Basic Information
var pferdeName: String,
var geschlecht: PferdeGeschlechtE,
var geburtsdatum: LocalDate? = null,
var rasse: String? = null,
var farbe: String? = null,
// Ownership and Responsibility
@Serializable(with = UuidSerializer::class)
var besitzerId: Uuid? = null,
@Serializable(with = UuidSerializer::class)
var verantwortlichePersonId: Uuid? = null,
// Breeding Information
var zuechterName: String? = null,
var zuchtbuchNummer: String? = null,
// Identification Numbers
var lebensnummer: String? = null,
var chipNummer: String? = null,
var passNummer: String? = null,
var oepsNummer: String? = null,
var feiNummer: String? = null,
// Pedigree Information
var vaterName: String? = null,
var mutterName: String? = null,
var mutterVaterName: String? = null,
// Physical Characteristics
var stockmass: Int? = null, // Height in cm
// Status and Administrative
var istAktiv: Boolean = true,
var bemerkungen: String? = null,
var datenQuelle: DatenQuelleE = DatenQuelleE.MANUELL,
// Audit Fields
@Serializable(with = InstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
) {
/**
* Returns the display name for the horse, combining name and birth year if available.
*/
fun getDisplayName(): String {
return geburtsdatum?.let { birthDate ->
"$pferdeName (${birthDate.year})"
} ?: pferdeName
}
/**
* Checks if the horse has complete identification information.
*/
fun hasCompleteIdentification(): Boolean {
return !lebensnummer.isNullOrBlank() ||
!chipNummer.isNullOrBlank() ||
!passNummer.isNullOrBlank()
}
/**
* Checks if the horse is registered with OEPS.
*/
fun isOepsRegistered(): Boolean {
return !oepsNummer.isNullOrBlank()
}
/**
* Checks if the horse is registered with FEI.
*/
fun isFeiRegistered(): Boolean {
return !feiNummer.isNullOrBlank()
}
/**
* Returns the age of the horse in years, or null if birth date is unknown.
*/
fun getAge(): Int? {
return geburtsdatum?.let { birthDate ->
val today = Clock.System.todayIn(kotlinx.datetime.TimeZone.currentSystemDefault())
var age = today.year - birthDate.year
// Check if a birthday has occurred this year
if (today.month.number < birthDate.month.number ||
(today.month.number == birthDate.month.number && today.day < birthDate.day)
) {
age--
}
age
}
}
/**
* Validates that required fields are present for horse registration.
*/
fun validateForRegistration(): List<String> {
val errors = mutableListOf<String>()
if (pferdeName.isBlank()) {
errors.add("Horse name is required")
}
if (!hasCompleteIdentification()) {
errors.add("At least one identification number (life number, chip number, or passport number) is required")
}
if (besitzerId == null) {
errors.add("Owner is required")
}
return errors
}
/**
* Creates a copy of this horse with an updated timestamp.
*/
fun withUpdatedTimestamp(): DomPferd {
return this.copy(updatedAt = Clock.System.now())
}
}
@@ -0,0 +1,136 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.domain.model.LizenzKlasseE
import at.mocode.core.domain.model.SparteE
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.LocalDateSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlinx.datetime.LocalDate
import kotlinx.serialization.Serializable
import kotlin.time.Clock
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Domain model representing a rider (Reiter) in the actor-context.
*
* A rider is a specialization of a person with additional equestrian-specific
* attributes such as license, start card, and competition eligibility.
* Data is primarily sourced from the OEPS ZNS (LIZENZ01.DAT).
*
* Key rules (ÖTO):
* - A rider requires an active Startkarte (annual fee paid) to compete nationally.
* - LizenzKlasse determines which competition classes the rider may enter.
* - Satznummer (6-digit) is the primary key for ZNS data exchange.
* - Kopfnummer is NOT a unique identifier it can change.
*
* @property reiterId Unique internal identifier (UUID).
* @property personId Reference to the base DomPerson record (UUID).
* @property satznummer 6-digit ZNS primary key for data exchange. Primary key for ZNS.
* @property lizenzNummer OEPS license number (from ZNS LIZENZ01.DAT).
* @property lizenzKlasse License class determining competition eligibility (e.g. R1, RD2).
* @property lizenzSparten Disciplines for which the license is valid.
* @property startkartAktiv Whether the annual start card fee has been paid.
* @property startkartSaison Season year for which the start card is valid (e.g. 2026).
* @property feiId FEI international rider ID (optional).
* @property nation Nation code (e.g. AUT).
* @property geburtsdatum Date of birth (for age class validation).
* @property vereinsNummer Club number (OEPS).
* @property vereinsName Club name.
* @property istGastreiter Whether the rider is a guest rider (foreign nationality, not in Austrian club).
* @property istAktiv Whether the rider is currently active in the system.
* @property datenQuelle Source of the data.
* @property createdAt Timestamp when this record was created.
* @property updatedAt Timestamp when this record was last updated.
*/
@Serializable
data class DomReiter(
@Serializable(with = UuidSerializer::class)
val reiterId: Uuid = Uuid.random(),
// Reference to base person
@Serializable(with = UuidSerializer::class)
val personId: Uuid,
// ZNS Identification
val satznummer: String,
val lizenzNummer: String? = null,
// License & Eligibility
val lizenzKlasse: LizenzKlasseE = LizenzKlasseE.LIZENZFREI,
val lizenzSparten: List<SparteE> = emptyList(),
// Start Card (Startkarte) annual fee proof
val startkartAktiv: Boolean = false,
val startkartSaison: Int? = null,
// International
val feiId: String? = null,
val nation: String? = null,
// Personal Data (denormalized from DomPerson for performance)
val nachname: String,
val vorname: String,
@Serializable(with = LocalDateSerializer::class)
val geburtsdatum: LocalDate? = null,
// Club Affiliation
val vereinsNummer: String? = null,
val vereinsName: String? = null,
// Status
val istGastreiter: Boolean = false,
val istAktiv: Boolean = true,
val datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
// Audit Fields
@Serializable(with = InstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
) {
/**
* Returns the display name of the rider.
*/
fun getDisplayName(): String = "$vorname $nachname"
/**
* Checks if the rider is eligible to compete nationally.
* Requires an active start card (Startkarte).
*/
fun isStartberechtigt(): Boolean = istAktiv && startkartAktiv
/**
* Checks if the rider holds a license for the given discipline.
*/
fun hasLizenzForSparte(sparte: SparteE): Boolean =
lizenzKlasse == LizenzKlasseE.LIZENZFREI || lizenzSparten.contains(sparte)
/**
* Validates the rider for competition entry.
* Returns a list of warning messages (never hard errors TBA has final say).
*/
fun validateForNennung(sparte: SparteE): List<String> {
val warnings = mutableListOf<String>()
if (!istAktiv) {
warnings.add("Reiter ${getDisplayName()} ist nicht aktiv")
}
if (!startkartAktiv) {
warnings.add("Reiter ${getDisplayName()} hat keine aktive Startkarte für Saison $startkartSaison")
}
if (!hasLizenzForSparte(sparte)) {
warnings.add("Reiter ${getDisplayName()} hat keine Lizenz für Sparte $sparte (Lizenzklasse: $lizenzKlasse)")
}
return warnings
}
/**
* Creates a copy of this rider with an updated timestamp.
*/
fun withUpdatedTimestamp(): DomReiter = this.copy(updatedAt = Clock.System.now())
}
@@ -0,0 +1,121 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlinx.serialization.Serializable
import kotlin.time.Clock
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Domain-Modell für einen Verein im actor-context.
*
* Repräsentiert einen OEPS-Mitgliedsverein, der als Veranstalter von Turnieren
* und als Heimverein von Reitern und Funktionären fungiert.
* Daten werden primär aus dem ZNS (VEREIN01.dat) importiert.
*
* Aggregate Root des `clubs`-Bounded Context.
*
* @property vereinId Eindeutige interne ID (UUID).
* @property vereinsNummer ÖPS-Vereinsnummer aus ZNS (VEREIN01.dat), 4-stellig. Primärschlüssel für ZNS-Datenaustausch.
* @property name Offizieller Vereinsname.
* @property kurzname Kurzbezeichnung des Vereins (optional).
* @property bundesland Bundesland, in dem der Verein ansässig ist.
* @property ort Ort / Stadt des Vereinssitzes.
* @property plz Postleitzahl.
* @property strasse Straße und Hausnummer.
* @property email Offizielle E-Mail-Adresse des Vereins.
* @property telefon Telefonnummer des Vereins.
* @property website Website-URL des Vereins.
* @property oepsRegionNummer Regionsnummer beim OEPS (Landesverband).
* @property istVeranstalter Ob der Verein als Veranstalter von Turnieren zugelassen ist.
* @property istAktiv Ob der Verein aktuell aktiv ist.
* @property bemerkungen Interne Notizen.
* @property datenQuelle Herkunft des Datensatzes (ZNS-Import oder manuell).
* @property createdAt Erstellungszeitpunkt.
* @property updatedAt Letzter Änderungszeitpunkt.
*/
@Serializable
data class DomVerein(
@Serializable(with = UuidSerializer::class)
val vereinId: Uuid = Uuid.random(),
// Identifikation
val vereinsNummer: String,
// Stammdaten
var name: String,
var kurzname: String? = null,
// Adresse
var bundesland: String? = null,
var ort: String? = null,
var plz: String? = null,
var strasse: String? = null,
// Kontakt
var email: String? = null,
var telefon: String? = null,
var website: String? = null,
// OEPS-Verwaltung
var oepsRegionNummer: String? = null,
var istVeranstalter: Boolean = false,
// Status & Verwaltung
var istAktiv: Boolean = true,
var bemerkungen: String? = null,
var datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
// Audit
@Serializable(with = InstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
) {
/**
* Gibt den Anzeigenamen zurück Kurzname bevorzugt, sonst vollständiger Name.
*/
fun getDisplayName(): String = kurzname ?: name
/**
* Gibt den vollständigen Anzeigenamen mit Vereinsnummer zurück.
*/
fun getDisplayNameWithNummer(): String = "${getDisplayName()} ($vereinsNummer)"
/**
* Prüft, ob vollständige Adressdaten vorhanden sind.
*/
fun hasCompleteAddress(): Boolean =
!ort.isNullOrBlank() && !plz.isNullOrBlank() && !strasse.isNullOrBlank()
/**
* Validiert den Verein für den Einsatz als Veranstalter.
* Gibt Warnungen zurück (kein harter Fehler Override-Event möglich).
*/
fun validateFuerVeranstaltung(): List<String> {
val warnings = mutableListOf<String>()
if (!istAktiv) {
warnings.add("Verein ${getDisplayName()} ist nicht aktiv.")
}
if (!istVeranstalter) {
warnings.add("Verein ${getDisplayName()} ist nicht als Veranstalter zugelassen.")
}
if (!hasCompleteAddress()) {
warnings.add("Verein ${getDisplayName()} hat keine vollständige Adresse hinterlegt.")
}
return warnings
}
/**
* Erstellt eine Kopie mit aktualisiertem Zeitstempel.
*/
fun withUpdatedTimestamp(): DomVerein = this.copy(updatedAt = Clock.System.now())
}
@@ -1,12 +1,11 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Definiert ein Land/eine Nation mit seinen offiziellen Codes und Bezeichnungen.
@@ -44,8 +43,8 @@ data class LandDefinition(
var istAktiv: Boolean = true,
var sortierReihenfolge: Int? = null,
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
@Serializable(with = InstantSerializer::class)
val createdAt: Instant,
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant
)
@@ -2,12 +2,11 @@
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.model.PlatzTypE
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
import kotlin.time.Instant
import kotlin.uuid.Uuid
/**
* Definiert einen Turnierplatz oder eine Wettkampfstätte.
@@ -41,8 +40,8 @@ data class Platz(
var istAktiv: Boolean = true,
var sortierReihenfolge: Int? = null,
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
@Serializable(with = InstantSerializer::class)
val createdAt: Instant,
@Serializable(with = InstantSerializer::class)
var updatedAt: Instant
)
@@ -0,0 +1,144 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.SparteE
import at.mocode.masterdata.domain.model.AltersklasseDefinition
import kotlin.uuid.Uuid
/**
* Repository interface for AltersklasseDefinition (Age Class) domain operations.
*
* This interface defines the contract for age class 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 AltersklasseRepository {
/**
* Finds an age class by its unique ID.
*
* @param id The unique identifier of the age class
* @return The age class if found, null otherwise
*/
suspend fun findById(id: Uuid): AltersklasseDefinition?
/**
* Finds an age class by its code.
*
* @param altersklasseCode The age class code (e.g., "JGD_U16", "JUN_U18")
* @return The age class if found, null otherwise
*/
suspend fun findByCode(altersklasseCode: String): AltersklasseDefinition?
/**
* Finds age classes by name (partial match).
*
* @param searchTerm The search term to match against age class names
* @param limit Maximum number of results to return
* @return List of matching age classes
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<AltersklasseDefinition>
/**
* Finds all active age classes.
*
* @param sparteFilter Optional filter by sport type
* @param geschlechtFilter Optional filter by gender ('M', 'W')
* @return List of active age classes
*/
suspend fun findAllActive(sparteFilter: SparteE? = null, geschlechtFilter: Char? = null): List<AltersklasseDefinition>
/**
* Finds age classes applicable for a specific age.
*
* @param age The age to check
* @param sparteFilter Optional filter by sport type
* @param geschlechtFilter Optional filter by gender ('M', 'W')
* @return List of applicable age classes
*/
suspend fun findApplicableForAge(
age: Int,
sparteFilter: SparteE? = null,
geschlechtFilter: Char? = null
): List<AltersklasseDefinition>
/**
* Finds age classes by sport type.
*
* @param sparte The sport type
* @param activeOnly Whether to return only active age classes
* @return List of age classes for the sport type
*/
suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by gender filter.
*
* @param geschlecht The gender ('M', 'W')
* @param activeOnly Whether to return only active age classes
* @return List of age classes for the gender
*/
suspend fun findByGeschlecht(geschlecht: Char, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by age range.
*
* @param minAge Minimum age (inclusive)
* @param maxAge Maximum age (inclusive)
* @param activeOnly Whether to return only active age classes
* @return List of age classes within the age range
*/
suspend fun findByAgeRange(minAge: Int?, maxAge: Int?, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by OETO rule reference.
*
* @param oetoRegelReferenzId The OETO rule reference ID
* @return List of age classes linked to the rule
*/
suspend fun findByOetoRegelReferenz(oetoRegelReferenzId: Uuid): List<AltersklasseDefinition>
/**
* Saves an age class (create or update).
*
* @param altersklasse The age class to save
* @return The saved age class with updated timestamps
*/
suspend fun save(altersklasse: AltersklasseDefinition): AltersklasseDefinition
/**
* Deletes an age class by ID.
*
* @param id The unique identifier of the age class to delete
* @return true if the age class was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Checks if an age class with the given code exists.
*
* @param altersklasseCode The age class code to check
* @return true if an age class with this code exists, false otherwise
*/
suspend fun existsByCode(altersklasseCode: String): Boolean
/**
* Counts the total number of active age classes.
*
* @param sparteFilter Optional filter by sport type
* @return The total count of active age classes
*/
suspend fun countActive(sparteFilter: SparteE? = null): Long
/**
* Validates if a person with given age and gender can participate in an age class.
*
* @param altersklasseId The age class ID
* @param age The person's age
* @param geschlecht The person's gender ('M', 'W')
* @return true if the person can participate, false otherwise
*/
suspend fun isEligible(altersklasseId: Uuid, age: Int, geschlecht: Char): Boolean
}
@@ -0,0 +1,93 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.FunktionaerRolleE
import at.mocode.core.domain.model.RichterQualifikationE
import at.mocode.core.domain.model.SparteE
import at.mocode.masterdata.domain.model.DomFunktionaer
import kotlin.uuid.Uuid
/**
* Repository-Interface für DomFunktionaer (Funktionär) Domain-Operationen.
*
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
* von konkreten Implementierungsdetails (Datenbank, etc.).
*/
interface FunktionaerRepository {
/**
* Sucht einen Funktionär anhand seiner eindeutigen ID.
*/
suspend fun findById(id: Uuid): DomFunktionaer?
/**
* Sucht einen Funktionär anhand seiner Richternummer.
*/
suspend fun findByRichterNummer(richterNummer: String): DomFunktionaer?
/**
* Sucht Funktionäre anhand von Vor- und/oder Nachname (Teilübereinstimmung).
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomFunktionaer>
/**
* Sucht alle Funktionäre mit einer bestimmten Rolle.
*/
suspend fun findByRolle(rolle: FunktionaerRolleE, activeOnly: Boolean = true): List<DomFunktionaer>
/**
* Sucht alle Richter mit einer bestimmten Qualifikation.
*/
suspend fun findByRichterQualifikation(
qualifikation: RichterQualifikationE,
activeOnly: Boolean = true
): List<DomFunktionaer>
/**
* Sucht alle Funktionäre, die für eine bestimmte Sparte qualifiziert sind.
*/
suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean = true): List<DomFunktionaer>
/**
* Sucht alle Funktionäre eines bestimmten Vereins.
*/
suspend fun findByVereinsNummer(vereinsNummer: String, activeOnly: Boolean = true): List<DomFunktionaer>
/**
* Gibt alle aktiven Funktionäre zurück (paginiert).
*/
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<DomFunktionaer>
/**
* Gibt alle Funktionäre zurück (paginiert).
*/
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomFunktionaer>
/**
* Speichert einen Funktionär (Insert oder Update).
*/
suspend fun save(funktionaer: DomFunktionaer): DomFunktionaer
/**
* Löscht einen Funktionär anhand seiner ID.
*
* @return true wenn gelöscht, false wenn nicht gefunden
*/
suspend fun delete(id: Uuid): Boolean
/**
* Zählt alle aktiven Funktionäre.
*/
suspend fun countActive(): Long
/**
* Zählt alle Richter (Rolle = RICHTER) mit einer bestimmten Qualifikation.
*/
suspend fun countByRichterQualifikation(qualifikation: RichterQualifikationE, activeOnly: Boolean = true): Long
/**
* Prüft ob ein Funktionär mit der gegebenen Richternummer bereits existiert.
*/
suspend fun existsByRichterNummer(richterNummer: String): Boolean
}
@@ -0,0 +1,248 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.masterdata.domain.model.DomPferd
import at.mocode.core.domain.model.PferdeGeschlechtE
import kotlin.uuid.Uuid
/**
* Repository interface for DomPferd (Horse) domain operations.
*
* This interface defines the contract for horse 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 HorseRepository {
/**
* Finds a horse by its unique ID.
*
* @param id The unique identifier of the horse
* @return The horse if found, null otherwise
*/
suspend fun findById(id: Uuid): DomPferd?
/**
* Finds a horse by its life number (Lebensnummer).
*
* @param lebensnummer The life number to search for
* @return The horse if found, null otherwise
*/
suspend fun findByLebensnummer(lebensnummer: String): DomPferd?
/**
* Finds a horse by its chip number.
*
* @param chipNummer The chip number to search for
* @return The horse if found, null otherwise
*/
suspend fun findByChipNummer(chipNummer: String): DomPferd?
/**
* Finds a horse by its passport number.
*
* @param passNummer The passport number to search for
* @return The horse if found, null otherwise
*/
suspend fun findByPassNummer(passNummer: String): DomPferd?
/**
* Finds a horse by its OEPS number.
*
* @param oepsNummer The OEPS number to search for
* @return The horse if found, null otherwise
*/
suspend fun findByOepsNummer(oepsNummer: String): DomPferd?
/**
* Finds a horse by its FEI number.
*
* @param feiNummer The FEI number to search for
* @return The horse if found, null otherwise
*/
suspend fun findByFeiNummer(feiNummer: String): DomPferd?
/**
* Finds horses by name (partial match).
*
* @param searchTerm The search term to match against horse names
* @param limit Maximum number of results to return
* @return List of matching horses
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomPferd>
/**
* Finds all horses owned by a specific person.
*
* @param ownerId The ID of the owner (from member-management context)
* @param activeOnly Whether to return only active horses
* @return List of horses owned by the person
*/
suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean = true): List<DomPferd>
/**
* Finds all horses for which a person is responsible.
*
* @param responsiblePersonId The ID of the responsible person
* @param activeOnly Whether to return only active horses
* @return List of horses for which the person is responsible
*/
suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean = true): List<DomPferd>
/**
* Finds horses by gender.
*
* @param geschlecht The gender to filter by
* @param activeOnly Whether to return only active horses
* @param limit Maximum number of results to return
* @return List of horses with the specified gender
*/
suspend fun findByGeschlecht(
geschlecht: PferdeGeschlechtE,
activeOnly: Boolean = true,
limit: Int = 100
): List<DomPferd>
/**
* Finds horses by breed.
*
* @param rasse The breed to filter by
* @param activeOnly Whether to return only active horses
* @param limit Maximum number of results to return
* @return List of horses of the specified breed
*/
suspend fun findByRasse(rasse: String, activeOnly: Boolean = true, limit: Int = 100): List<DomPferd>
/**
* Finds horses by birth year.
*
* @param birthYear The birth year to filter by
* @param activeOnly Whether to return only active horses
* @return List of horses born in the specified year
*/
suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean = true): List<DomPferd>
/**
* Finds horses by birth year range.
*
* @param fromYear The start year (inclusive)
* @param toYear The end year (inclusive)
* @param activeOnly Whether to return only active horses
* @return List of horses born within the specified year range
*/
suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean = true): List<DomPferd>
/**
* Finds all active horses.
*
* @param limit Maximum number of results to return
* @return List of active horses
*/
suspend fun findAllActive(limit: Int = 1000): List<DomPferd>
/**
* Finds horses with OEPS registration.
*
* @param activeOnly Whether to return only active horses
* @return List of OEPS registered horses
*/
suspend fun findOepsRegistered(activeOnly: Boolean = true): List<DomPferd>
/**
* Finds horses with FEI registration.
*
* @param activeOnly Whether to return only active horses
* @return List of FEI registered horses
*/
suspend fun findFeiRegistered(activeOnly: Boolean = true): List<DomPferd>
/**
* Saves a horse (create or update).
*
* @param horse The horse to save
* @return The saved horse with updated timestamps
*/
suspend fun save(horse: DomPferd): DomPferd
/**
* Deletes a horse by ID.
*
* @param id The unique identifier of the horse to delete
* @return true if the horse was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Checks if a horse with the given life number exists.
*
* @param lebensnummer The life number to check
* @return true if a horse with this life number exists, false otherwise
*/
suspend fun existsByLebensnummer(lebensnummer: String): Boolean
/**
* Checks if a horse with the given chip number exists.
*
* @param chipNummer The chip number to check
* @return true if a horse with this chip number exists, false otherwise
*/
suspend fun existsByChipNummer(chipNummer: String): Boolean
/**
* Checks if a horse with the given passport number exists.
*
* @param passNummer The passport number to check
* @return true if a horse with this passport number exists, false otherwise
*/
suspend fun existsByPassNummer(passNummer: String): Boolean
/**
* Checks if a horse with the given OEPS number exists.
*
* @param oepsNummer The OEPS number to check
* @return true if a horse with this OEPS number exists, false otherwise
*/
suspend fun existsByOepsNummer(oepsNummer: String): Boolean
/**
* Checks if a horse with the given FEI number exists.
*
* @param feiNummer The FEI number to check
* @return true if a horse with this FEI number exists, false otherwise
*/
suspend fun existsByFeiNummer(feiNummer: String): Boolean
/**
* Counts the total number of active horses.
*
* @return The total count of active horses
*/
suspend fun countActive(): Long
/**
* Counts horses by owner.
*
* @param ownerId The ID of the owner
* @param activeOnly Whether to count only active horses
* @return The count of horses owned by the person
*/
suspend fun countByOwnerId(ownerId: Uuid, activeOnly: Boolean = true): Long
/**
* Counts horses with OEPS registration.
*
* @param activeOnly Whether to count only active horses
* @return The count of OEPS registered horses
*/
suspend fun countOepsRegistered(activeOnly: Boolean = true): Long
/**
* Counts horses with FEI registration.
*
* @param activeOnly Whether to count only active horses
* @return The count of FEI registered horses
*/
suspend fun countFeiRegistered(activeOnly: Boolean = true): Long
}
@@ -0,0 +1,89 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.LizenzKlasseE
import at.mocode.core.domain.model.SparteE
import at.mocode.masterdata.domain.model.DomReiter
import kotlin.uuid.Uuid
/**
* Repository-Interface für DomReiter (Reiter) Domain-Operationen.
*
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
* von konkreten Implementierungsdetails (Datenbank, etc.).
*/
interface ReiterRepository {
/**
* Sucht einen Reiter anhand seiner eindeutigen ID.
*/
suspend fun findById(id: Uuid): DomReiter?
/**
* Sucht einen Reiter anhand seiner Satznummer (OEPS-Mitgliedsnummer).
*/
suspend fun findBySatznummer(satznummer: String): DomReiter?
/**
* Sucht einen Reiter anhand seiner FEI-ID.
*/
suspend fun findByFeiId(feiId: String): DomReiter?
/**
* Sucht Reiter anhand von Vor- und/oder Nachname (Teilübereinstimmung).
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomReiter>
/**
* Sucht alle Reiter eines bestimmten Vereins.
*/
suspend fun findByVereinsNummer(vereinsNummer: String, activeOnly: Boolean = true): List<DomReiter>
/**
* Sucht alle Reiter mit einer bestimmten Lizenzklasse.
*/
suspend fun findByLizenzKlasse(lizenzKlasse: LizenzKlasseE, activeOnly: Boolean = true): List<DomReiter>
/**
* Sucht alle Reiter, die für eine bestimmte Sparte lizenziert sind.
*/
suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean = true): List<DomReiter>
/**
* Sucht alle Gastreiter.
*/
suspend fun findGastreiter(activeOnly: Boolean = true): List<DomReiter>
/**
* Gibt alle aktiven Reiter zurück (paginiert).
*/
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<DomReiter>
/**
* Gibt alle Reiter zurück (paginiert).
*/
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomReiter>
/**
* Speichert einen Reiter (Insert oder Update).
*/
suspend fun save(reiter: DomReiter): DomReiter
/**
* Löscht einen Reiter anhand seiner ID.
*
* @return true wenn gelöscht, false wenn nicht gefunden
*/
suspend fun delete(id: Uuid): Boolean
/**
* Zählt alle aktiven Reiter.
*/
suspend fun countActive(): Long
/**
* Prüft ob ein Reiter mit der gegebenen Satznummer bereits existiert.
*/
suspend fun existsBySatznummer(satznummer: String): Boolean
}
@@ -0,0 +1,72 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.masterdata.domain.model.DomVerein
import kotlin.uuid.Uuid
/**
* Repository-Interface für DomVerein (Verein) Domain-Operationen.
*
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
* von konkreten Implementierungsdetails (Datenbank etc.).
*/
interface VereinRepository {
/**
* Sucht einen Verein anhand seiner eindeutigen ID.
*/
suspend fun findById(id: Uuid): DomVerein?
/**
* Sucht einen Verein anhand seiner OEPS-Vereinsnummer.
*/
suspend fun findByVereinsNummer(vereinsNummer: String): DomVerein?
/**
* Sucht Vereine anhand des Namens (Teilübereinstimmung).
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomVerein>
/**
* Sucht alle Vereine eines Bundeslandes.
*/
suspend fun findByBundesland(bundesland: String, activeOnly: Boolean = true): List<DomVerein>
/**
* Sucht alle Vereine, die als Veranstalter markiert sind.
*/
suspend fun findVeranstalter(activeOnly: Boolean = true): List<DomVerein>
/**
* Gibt alle aktiven Vereine zurück (paginiert).
*/
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<DomVerein>
/**
* Gibt alle Vereine zurück (paginiert).
*/
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomVerein>
/**
* Speichert einen Verein (Insert oder Update).
*/
suspend fun save(verein: DomVerein): DomVerein
/**
* Löscht einen Verein anhand seiner ID.
*
* @return true wenn gelöscht, false wenn nicht gefunden
*/
suspend fun delete(id: Uuid): Boolean
/**
* Zählt alle aktiven Vereine.
*/
suspend fun countActive(): Long
/**
* Prüft ob ein Verein mit der gegebenen Vereinsnummer bereits existiert.
*/
suspend fun existsByVereinsNummer(vereinsNummer: String): Boolean
}
@@ -1,139 +0,0 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.SparteE
import at.mocode.masterdata.domain.model.AltersklasseDefinition
import kotlin.uuid.Uuid
/**
* Repository interface for AltersklasseDefinition (Age Class) domain operations.
*
* This interface defines the contract for age class 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 AltersklasseRepository {
/**
* Finds an age class by its unique ID.
*
* @param id The unique identifier of the age class
* @return The age class if found, null otherwise
*/
suspend fun findById(id: Uuid): AltersklasseDefinition?
/**
* Finds an age class by its code.
*
* @param altersklasseCode The age class code (e.g., "JGD_U16", "JUN_U18")
* @return The age class if found, null otherwise
*/
suspend fun findByCode(altersklasseCode: String): AltersklasseDefinition?
/**
* Finds age classes by name (partial match).
*
* @param searchTerm The search term to match against age class names
* @param limit Maximum number of results to return
* @return List of matching age classes
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<AltersklasseDefinition>
/**
* Finds all active age classes.
*
* @param sparteFilter Optional filter by sport type
* @param geschlechtFilter Optional filter by gender ('M', 'W')
* @return List of active age classes
*/
suspend fun findAllActive(sparteFilter: SparteE? = null, geschlechtFilter: Char? = null): List<AltersklasseDefinition>
/**
* Finds age classes applicable for a specific age.
*
* @param age The age to check
* @param sparteFilter Optional filter by sport type
* @param geschlechtFilter Optional filter by gender ('M', 'W')
* @return List of applicable age classes
*/
suspend fun findApplicableForAge(age: Int, sparteFilter: SparteE? = null, geschlechtFilter: Char? = null): List<AltersklasseDefinition>
/**
* Finds age classes by sport type.
*
* @param sparte The sport type
* @param activeOnly Whether to return only active age classes
* @return List of age classes for the sport type
*/
suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by gender filter.
*
* @param geschlecht The gender ('M', 'W')
* @param activeOnly Whether to return only active age classes
* @return List of age classes for the gender
*/
suspend fun findByGeschlecht(geschlecht: Char, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by age range.
*
* @param minAge Minimum age (inclusive)
* @param maxAge Maximum age (inclusive)
* @param activeOnly Whether to return only active age classes
* @return List of age classes within the age range
*/
suspend fun findByAgeRange(minAge: Int?, maxAge: Int?, activeOnly: Boolean = true): List<AltersklasseDefinition>
/**
* Finds age classes by OETO rule reference.
*
* @param oetoRegelReferenzId The OETO rule reference ID
* @return List of age classes linked to the rule
*/
suspend fun findByOetoRegelReferenz(oetoRegelReferenzId: Uuid): List<AltersklasseDefinition>
/**
* Saves an age class (create or update).
*
* @param altersklasse The age class to save
* @return The saved age class with updated timestamps
*/
suspend fun save(altersklasse: AltersklasseDefinition): AltersklasseDefinition
/**
* Deletes an age class by ID.
*
* @param id The unique identifier of the age class to delete
* @return true if the age class was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Checks if an age class with the given code exists.
*
* @param altersklasseCode The age class code to check
* @return true if an age class with this code exists, false otherwise
*/
suspend fun existsByCode(altersklasseCode: String): Boolean
/**
* Counts the total number of active age classes.
*
* @param sparteFilter Optional filter by sport type
* @return The total count of active age classes
*/
suspend fun countActive(sparteFilter: SparteE? = null): Long
/**
* Validates if a person with given age and gender can participate in an age class.
*
* @param altersklasseId The age class ID
* @param age The person's age
* @param geschlecht The person's gender ('M', 'W')
* @return true if the person can participate, false otherwise
*/
suspend fun isEligible(altersklasseId: Uuid, age: Int, geschlecht: Char): Boolean
}