fixing web-app

This commit is contained in:
stefan
2025-09-24 14:21:57 +02:00
parent cd2b0796a6
commit 1c4184809a
156 changed files with 440 additions and 1708 deletions
@@ -0,0 +1,27 @@
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.serialization)
}
kotlin {
jvm()
js(IR) {
browser()
}
sourceSets {
val commonMain by getting {
dependencies {
// KORREKTUR: Diese zwei Zeilen hinzufügen
implementation(projects.core.coreDomain)
implementation(projects.core.coreUtils)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(projects.platform.platformTesting)
}
}
}
}
@@ -0,0 +1,59 @@
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.serialization.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
/**
* Definiert eine spezifische Altersklasse für Teilnehmer (Reiter, Fahrer, Voltigierer)
* oder ggf. auch für Pferde, basierend auf den Vorgaben der ÖTO oder anderer Regelwerke.
*
* Beispiele: "Jugend U16", "Junioren U18", "Junge Reiter U21", "Allgemeine Klasse",
* "Pony Jugend U14", "Senioren Ü40".
* Diese Definitionen dienen zur Überprüfung von Teilnahmeberechtigungen in Bewerben und Abteilungen.
*
* @property altersklasseId Eindeutiger interner Identifikator für diese Altersklassendefinition (UUID).
* @property altersklasseCode Ein eindeutiges Kürzel oder Code für die Altersklasse
* (z.B. "JGD_U16", "JUN_U18", "YR_U21", "AK", "PONY_U14"). Dient als fachlicher Schlüssel.
* @property bezeichnung Die offizielle oder allgemein verständliche Bezeichnung der Altersklasse.
* @property minAlter Das Mindestalter (Jahre, inklusive) für diese Altersklasse. `null`, wenn es keine Untergrenze gibt.
* @property maxAlter Das Höchstalter (Jahre, inklusive) für diese Altersklasse. `null`, wenn es keine Obergrenze gibt.
* @property stichtagRegelText Eine Beschreibung der Regel für den Stichtag zur Altersberechnung
* (z.B. "31.12. des laufenden Kalenderjahres", "Geburtstag im laufenden Jahr").
* @property sparteFilter Optionale Angabe, ob diese Altersklassendefinition nur für eine spezifische Sparte gilt.
* @property geschlechtFilter Optionaler Filter für das Geschlecht ('M', 'W'), falls die Altersklasse geschlechtsspezifisch ist.
* `null` bedeutet für alle Geschlechter gültig.
* @property oetoRegelReferenzId Optionale Verknüpfung zu einer spezifischen Regel in der `OETORegelReferenz`-Tabelle,
* die diese Altersklasse definiert.
* @property istAktiv Gibt an, ob diese Altersklassendefinition aktuell im System verwendet werden kann.
* @property createdAt Zeitstempel der Erstellung dieses Datensatzes.
* @property updatedAt Zeitstempel der letzten Aktualisierung dieses Datensatzes.
*/
@Serializable
data class AltersklasseDefinition(
@Serializable(with = UuidSerializer::class)
val altersklasseId: Uuid = uuid4(), // Interner Primärschlüssel
var altersklasseCode: String, // Fachlicher PK, z.B. "JGD_U16"
var bezeichnung: String,
var minAlter: Int? = null,
var maxAlter: Int? = null,
var stichtagRegelText: String? = "31.12. des laufenden Kalenderjahres", // Typischer Default
var sparteFilter: SparteE? = null, // Ist diese Definition spartenspezifisch?
var geschlechtFilter: Char? = null, // 'M', 'W', oder null für beide
@Serializable(with = UuidSerializer::class)
var oetoRegelReferenzId: Uuid? = null, // FK zu OETORegelReferenz.oetoRegelReferenzId
var istAktiv: Boolean = true,
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
)
@@ -0,0 +1,51 @@
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
/**
* Definiert ein Bundesland oder eine vergleichbare subnationale Verwaltungseinheit.
*
* Diese Entität ist primär für die österreichischen Bundesländer mit ihren OEPS-spezifischen
* Codes gedacht, kann aber auch für Bundesländer/Regionen anderer Nationen erweitert werden.
*
* @property bundeslandId Eindeutiger interner Identifikator für dieses Bundesland (UUID).
* @property landId Fremdschlüssel zur `LandDefinition`, dem dieses Bundesland angehört.
* @property oepsCode Der 2-stellige numerische OEPS-Code für österreichische Bundesländer
* (z.B. "01" für Wien, "02" für Niederösterreich). Sollte eindeutig sein für Land "Österreich".
* @property iso3166_2_Code Optionaler offizieller ISO 3166-2 Code für das Bundesland
* (z.B. "AT-1" für Burgenland, "DE-BY" für Bayern).
* @property name Der offizielle Name des Bundeslandes.
* @property kuerzel Ein gängiges Kürzel für das Bundesland (z.B. "NÖ", "W", "STMK").
* @property wappenUrl Optionaler URL-Pfad zu einer Bilddatei des Bundeslandwappens.
* @property istAktiv Gibt an, ob dieses Bundesland aktuell im System ausgewählt/verwendet werden kann.
* @property sortierReihenfolge Optionale Zahl zur Steuerung der Sortierreihenfolge in Auswahllisten.
* @property createdAt Zeitstempel der Erstellung dieses Datensatzes.
* @property updatedAt Zeitstempel der letzten Aktualisierung dieses Datensatzes.
*/
@Serializable
data class BundeslandDefinition(
@Serializable(with = UuidSerializer::class)
val bundeslandId: Uuid = uuid4(),
@Serializable(with = UuidSerializer::class)
var landId: Uuid, // FK zu LandDefinition.landId
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"
var kuerzel: String? = null, // z.B. "NÖ", "BY"
var wappenUrl: String? = null,
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()
)
@@ -0,0 +1,51 @@
package at.mocode.masterdata.domain.model
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
/**
* Definiert ein Land/eine Nation mit seinen offiziellen Codes und Bezeichnungen.
*
* Diese Entität dient als zentrale Referenz für Länder, die im System für
* Nationalitäten von Personen, Vereinen oder für internationale Turniere relevant sind.
*
* @property landId Eindeutiger interner Identifikator für dieses Land (UUID).
* @property isoAlpha2Code Der 2-stellige ISO 3166-1 Alpha-2 Code des Landes (z.B. "AT", "DE"). Sollte eindeutig sein.
* @property isoAlpha3Code Der 3-stellige ISO 3166-1 Alpha-3 Code des Landes (z.B. "AUT", "DEU"). Sollte eindeutig sein.
* @property isoNumerischerCode Optionaler 3-stelliger numerischer ISO 3166-1 Code des Landes (z.B. "040" für Österreich).
* @property nameDeutsch Der offizielle deutsche Name des Landes.
* @property nameEnglisch Der offizielle englische Name des Landes.
* @property wappenUrl Optionaler URL-Pfad zu einer Bilddatei des Länderwappens oder der Flagge.
* @property istEuMitglied Gibt an, ob das Land Mitglied der Europäischen Union ist.
* @property istEwrMitglied Gibt an, ob das Land Mitglied des Europäischen Wirtschaftsraums ist.
* @property istAktiv Gibt an, ob dieses Land aktuell im System ausgewählt/verwendet werden kann.
* @property sortierReihenfolge Optionale Zahl zur Steuerung der Sortierreihenfolge in Auswahllisten.
* @property createdAt Zeitstempel der Erstellung dieses Datensatzes.
* @property updatedAt Zeitstempel der letzten Aktualisierung dieses Datensatzes.
*/
@Serializable
data class LandDefinition(
@Serializable(with = UuidSerializer::class)
val landId: Uuid = uuid4(),
var isoAlpha2Code: String, // z.B. "AT" → Fachlicher PK oder Unique Constraint
var isoAlpha3Code: String, // z.B. "AUT" -> Unique Constraint
var isoNumerischerCode: String? = null, // z.B. "040"
var nameDeutsch: String, // z.B. "Österreich"
var nameEnglisch: String? = null, // z.B. "Austria"
var wappenUrl: String? = null,
var istEuMitglied: Boolean? = null,
var istEwrMitglied: Boolean? = null, // Europäischer Wirtschaftsraum
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()
)
@@ -0,0 +1,48 @@
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.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
/**
* Definiert einen Turnierplatz oder eine Wettkampfstätte.
*
* Diese Entität repräsentiert die verschiedenen Plätze und Arenen, die bei Turnieren
* für verschiedene Disziplinen verwendet werden können.
*
* @property id Eindeutiger interner Identifikator für diesen Platz (UUID).
* @property turnierId Fremdschlüssel zum Turnier, zu dem dieser Platz gehört.
* @property name Der Name oder die Bezeichnung des Platzes (z.B. "Hauptplatz", "Dressurplatz A").
* @property dimension Die Abmessungen des Platzes (z.B. "20x60m", "20x40m").
* @property boden Die Art des Bodenbelags (z.B. "Sand", "Gras", "Kunststoff").
* @property typ Der Typ des Platzes (siehe PlatzTypE enum).
* @property istAktiv Gibt an, ob dieser Platz aktuell verwendet werden kann.
* @property sortierReihenfolge Optionale Zahl zur Steuerung der Sortierreihenfolge.
* @property createdAt Zeitstempel der Erstellung dieses Datensatzes.
* @property updatedAt Zeitstempel der letzten Aktualisierung dieses Datensatzes.
*/
@Serializable
data class Platz(
@Serializable(with = UuidSerializer::class)
val id: Uuid = uuid4(),
@Serializable(with = UuidSerializer::class)
var turnierId: Uuid,
var name: String,
var dimension: String? = null,
var boden: String? = null,
var typ: PlatzTypE,
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()
)
@@ -0,0 +1,138 @@
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.SparteE
import at.mocode.masterdata.domain.model.AltersklasseDefinition
import com.benasher44.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,109 @@
package at.mocode.masterdata.domain.repository
import at.mocode.masterdata.domain.model.BundeslandDefinition
import com.benasher44.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 {
/**
* 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
/**
* 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
}
@@ -0,0 +1,109 @@
package at.mocode.masterdata.domain.repository
import at.mocode.masterdata.domain.model.LandDefinition
import com.benasher44.uuid.Uuid
/**
* Repository interface for LandDefinition (Country) domain operations.
*
* This interface defines the contract for country 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 LandRepository {
/**
* Finds a country by its unique ID.
*
* @param id The unique identifier of the country
* @return The country if found, null otherwise
*/
suspend fun findById(id: Uuid): LandDefinition?
/**
* Finds a country by its ISO Alpha-2 code.
*
* @param isoAlpha2Code The 2-letter ISO code (e.g., "AT", "DE")
* @return The country if found, null otherwise
*/
suspend fun findByIsoAlpha2Code(isoAlpha2Code: String): LandDefinition?
/**
* Finds a country by its ISO Alpha-3 code.
*
* @param isoAlpha3Code The 3-letter ISO code (e.g., "AUT", "DEU")
* @return The country if found, null otherwise
*/
suspend fun findByIsoAlpha3Code(isoAlpha3Code: String): LandDefinition?
/**
* Finds countries by name (partial match on German or English name).
*
* @param searchTerm The search term to match against country names
* @param limit Maximum number of results to return
* @return List of matching countries
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<LandDefinition>
/**
* Finds all active countries.
*
* @param orderBySortierung Whether to order by sortierReihenfolge field
* @return List of active countries
*/
suspend fun findAllActive(orderBySortierung: Boolean = true): List<LandDefinition>
/**
* Finds all EU member countries.
*
* @return List of EU member countries
*/
suspend fun findEuMembers(): List<LandDefinition>
/**
* Finds all EWR (European Economic Area) member countries.
*
* @return List of EWR member countries
*/
suspend fun findEwrMembers(): List<LandDefinition>
/**
* Saves a country (create or update).
*
* @param land The country to save
* @return The saved country with updated timestamps
*/
suspend fun save(land: LandDefinition): LandDefinition
/**
* Deletes a country by ID.
*
* @param id The unique identifier of the country to delete
* @return true if the country was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Checks if a country with the given ISO Alpha-2 code exists.
*
* @param isoAlpha2Code The ISO Alpha-2 code to check
* @return true if a country with this code exists, false otherwise
*/
suspend fun existsByIsoAlpha2Code(isoAlpha2Code: String): Boolean
/**
* Checks if a country with the given ISO Alpha-3 code exists.
*
* @param isoAlpha3Code The ISO Alpha-3 code to check
* @return true if a country with this code exists, false otherwise
*/
suspend fun existsByIsoAlpha3Code(isoAlpha3Code: String): Boolean
/**
* Counts the total number of active countries.
*
* @return The total count of active countries
*/
suspend fun countActive(): Long
}
@@ -0,0 +1,150 @@
package at.mocode.masterdata.domain.repository
import at.mocode.core.domain.model.PlatzTypE
import at.mocode.masterdata.domain.model.Platz
import com.benasher44.uuid.Uuid
/**
* Repository interface for Platz (Venue/Arena) domain operations.
*
* This interface defines the contract for venue/arena 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 PlatzRepository {
/**
* Finds a venue by its unique ID.
*
* @param id The unique identifier of the venue
* @return The venue if found, null otherwise
*/
suspend fun findById(id: Uuid): Platz?
/**
* Finds all venues for a specific tournament.
*
* @param turnierId The tournament ID
* @param activeOnly Whether to return only active venues
* @param orderBySortierung Whether to order by sortierReihenfolge field
* @return List of venues for the tournament
*/
suspend fun findByTournament(turnierId: Uuid, activeOnly: Boolean = true, orderBySortierung: Boolean = true): List<Platz>
/**
* Finds venues by name (partial match).
*
* @param searchTerm The search term to match against venue names
* @param turnierId Optional tournament ID to limit search
* @param limit Maximum number of results to return
* @return List of matching venues
*/
suspend fun findByName(searchTerm: String, turnierId: Uuid? = null, limit: Int = 50): List<Platz>
/**
* Finds venues by type.
*
* @param typ The venue type
* @param turnierId Optional tournament ID to limit search
* @param activeOnly Whether to return only active venues
* @return List of venues of the specified type
*/
suspend fun findByType(typ: PlatzTypE, turnierId: Uuid? = null, activeOnly: Boolean = true): List<Platz>
/**
* Finds venues by ground type.
*
* @param boden The ground type (e.g., "Sand", "Gras", "Kunststoff")
* @param turnierId Optional tournament ID to limit search
* @param activeOnly Whether to return only active venues
* @return List of venues with the specified ground type
*/
suspend fun findByGroundType(boden: String, turnierId: Uuid? = null, activeOnly: Boolean = true): List<Platz>
/**
* Finds venues by dimensions.
*
* @param dimension The venue dimensions (e.g., "20x60m", "20x40m")
* @param turnierId Optional tournament ID to limit search
* @param activeOnly Whether to return only active venues
* @return List of venues with the specified dimensions
*/
suspend fun findByDimensions(dimension: String, turnierId: Uuid? = null, activeOnly: Boolean = true): List<Platz>
/**
* Finds all active venues.
*
* @param orderBySortierung Whether to order by sortierReihenfolge field
* @return List of active venues
*/
suspend fun findAllActive(orderBySortierung: Boolean = true): List<Platz>
/**
* Finds venues suitable for a specific discipline based on type and dimensions.
*
* @param requiredType The required venue type
* @param requiredDimensions Optional required dimensions
* @param turnierId Optional tournament ID to limit search
* @return List of suitable venues
*/
suspend fun findSuitableForDiscipline(
requiredType: PlatzTypE,
requiredDimensions: String? = null,
turnierId: Uuid? = null
): List<Platz>
/**
* Saves a venue (create or update).
*
* @param platz The venue to save
* @return The saved venue with updated timestamps
*/
suspend fun save(platz: Platz): Platz
/**
* Deletes a venue by ID.
*
* @param id The unique identifier of the venue to delete
* @return true if the venue was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Checks if a venue with the given name exists for a tournament.
*
* @param name The venue name to check
* @param turnierId The tournament ID
* @return true if a venue with this name exists, false otherwise
*/
suspend fun existsByNameAndTournament(name: String, turnierId: Uuid): Boolean
/**
* Counts the total number of active venues for a tournament.
*
* @param turnierId The tournament ID
* @return The total count of active venues
*/
suspend fun countActiveByTournament(turnierId: Uuid): Long
/**
* Counts venues by type for a tournament.
*
* @param typ The venue type
* @param turnierId The tournament ID
* @param activeOnly Whether to count only active venues
* @return The count of venues of the specified type
*/
suspend fun countByTypeAndTournament(typ: PlatzTypE, turnierId: Uuid, activeOnly: Boolean = true): Long
/**
* Finds available venues for a specific time slot (if scheduling is implemented).
* This method can be extended when venue scheduling functionality is added.
*
* @param turnierId The tournament ID
* @param startTime The start time (placeholder for future scheduling feature)
* @param endTime The end time (placeholder for future scheduling feature)
* @return List of available venues (currently returns all active venues)
*/
suspend fun findAvailableForTimeSlot(turnierId: Uuid, startTime: String? = null, endTime: String? = null): List<Platz>
}