refactor: Migrate from monolithic to modular architecture

- Restructure project into domain-specific modules (core, masterdata, members, horses, events, infrastructure)
- Create shared client components in common-ui module
- Implement CI/CD workflows with GitHub Actions
- Consolidate documentation in docs directory
- Remove deprecated modules and documentation files
- Add cleanup and migration scripts for transition
- Update README with new project structure and setup instructions
This commit is contained in:
stefan
2025-07-22 18:44:18 +02:00
parent 8229e8e571
commit a256622f37
314 changed files with 5930 additions and 19817 deletions
+9
View File
@@ -0,0 +1,9 @@
plugins {
kotlin("jvm")
}
dependencies {
implementation(projects.core.coreDomain)
implementation(projects.core.coreUtils)
testImplementation(projects.platform.platformTesting)
}
@@ -0,0 +1,15 @@
package at.mocode.events
/**
* Simple Event Management class for testing KMP configuration
*/
class EventManagement {
fun createEvent(name: String): String {
return "Event created: $name"
}
}
fun main() {
val eventManager = EventManagement()
println(eventManager.createEvent("Test Event"))
}
@@ -0,0 +1,132 @@
package at.mocode.events.domain.model
import at.mocode.core.domain.model.SparteE
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.KotlinLocalDateSerializer
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.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.serialization.Serializable
/**
* Domain model representing an event/competition in the event management system.
*
* This entity represents a sporting event that can contain multiple tournaments
* and competitions. It serves as the main aggregate root for event planning.
*
* @property veranstaltungId Unique internal identifier for this event (UUID).
* @property name Name of the event.
* @property beschreibung Description of the event.
* @property startDatum Start date of the event.
* @property endDatum End date of the event.
* @property ort Location where the event takes place.
* @property veranstalterVereinId ID of the organizing club/association.
* @property sparten List of sport disciplines included in this event.
* @property istAktiv Whether the event is currently active.
* @property istOeffentlich Whether the event is public.
* @property maxTeilnehmer Maximum number of participants (optional).
* @property anmeldeschluss Registration deadline.
* @property createdAt Timestamp when this record was created.
* @property updatedAt Timestamp when this record was last updated.
*/
@Serializable
data class Veranstaltung(
@Serializable(with = UuidSerializer::class)
val veranstaltungId: Uuid = uuid4(),
// Basic Information
var name: String,
var beschreibung: String? = null,
// Dates
@Serializable(with = KotlinLocalDateSerializer::class)
var startDatum: LocalDate,
@Serializable(with = KotlinLocalDateSerializer::class)
var endDatum: LocalDate,
// Location and Organization
var ort: String,
@Serializable(with = UuidSerializer::class)
var veranstalterVereinId: Uuid,
// Event Details
var sparten: List<SparteE> = emptyList(),
var istAktiv: Boolean = true,
var istOeffentlich: Boolean = true,
var maxTeilnehmer: Int? = null,
@Serializable(with = KotlinLocalDateSerializer::class)
var anmeldeschluss: LocalDate? = null,
// Audit Fields
@Serializable(with = KotlinInstantSerializer::class)
val createdAt: Instant = Clock.System.now(),
@Serializable(with = KotlinInstantSerializer::class)
var updatedAt: Instant = Clock.System.now()
) {
/**
* Checks if the event is currently accepting registrations.
*/
fun isRegistrationOpen(): Boolean {
// Simplified implementation - can be enhanced with proper date comparison
return istAktiv && anmeldeschluss != null
}
/**
* Returns the duration of the event in days.
*/
fun getDurationInDays(): Int {
return (endDatum.toEpochDays() - startDatum.toEpochDays()).toInt() + 1
}
/**
* Checks if the event spans multiple days.
*/
fun isMultiDay(): Boolean {
return startDatum != endDatum
}
/**
* Validates that the event data is consistent.
*/
fun validate(): List<String> {
val errors = mutableListOf<String>()
if (name.isBlank()) {
errors.add("Event name is required")
}
if (ort.isBlank()) {
errors.add("Event location is required")
}
if (endDatum < startDatum) {
errors.add("End date cannot be before start date")
}
anmeldeschluss?.let { deadline ->
if (deadline > startDatum) {
errors.add("Registration deadline cannot be after event start date")
}
}
maxTeilnehmer?.let { max ->
if (max <= 0) {
errors.add("Maximum participants must be positive")
}
}
return errors
}
/**
* Creates a copy of this event with updated timestamp.
*/
fun withUpdatedTimestamp(): Veranstaltung {
return this.copy(updatedAt = Clock.System.now())
}
}
@@ -0,0 +1,108 @@
package at.mocode.events.domain.repository
import at.mocode.events.domain.model.Veranstaltung
import com.benasher44.uuid.Uuid
import kotlinx.datetime.LocalDate
/**
* Repository interface for Veranstaltung (Event) entities.
*
* This interface defines the contract for data access operations
* related to events in the event management bounded context.
*/
interface VeranstaltungRepository {
/**
* Finds an event by its unique identifier.
*
* @param id The unique identifier of the event
* @return The event if found, null otherwise
*/
suspend fun findById(id: Uuid): Veranstaltung?
/**
* Finds events by name (partial match).
*
* @param searchTerm The search term to match against event names
* @param limit Maximum number of results to return
* @return List of matching events
*/
suspend fun findByName(searchTerm: String, limit: Int = 50): List<Veranstaltung>
/**
* Finds events organized by a specific club/association.
*
* @param vereinId The ID of the organizing club
* @param activeOnly Whether to return only active events
* @return List of events organized by the specified club
*/
suspend fun findByVeranstalterVereinId(vereinId: Uuid, activeOnly: Boolean = true): List<Veranstaltung>
/**
* Finds events within a date range.
*
* @param startDate The earliest start date to include
* @param endDate The latest end date to include
* @param activeOnly Whether to return only active events
* @return List of events within the specified date range
*/
suspend fun findByDateRange(startDate: LocalDate, endDate: LocalDate, activeOnly: Boolean = true): List<Veranstaltung>
/**
* Finds events starting on a specific date.
*
* @param date The date to search for
* @param activeOnly Whether to return only active events
* @return List of events starting on the specified date
*/
suspend fun findByStartDate(date: LocalDate, activeOnly: Boolean = true): List<Veranstaltung>
/**
* Finds all active events.
*
* @param limit Maximum number of results to return
* @param offset Number of results to skip
* @return List of active events
*/
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<Veranstaltung>
/**
* Finds public events (events that are open to public registration).
*
* @param activeOnly Whether to return only active events
* @return List of public events
*/
suspend fun findPublicEvents(activeOnly: Boolean = true): List<Veranstaltung>
/**
* Saves an event (insert or update).
*
* @param veranstaltung The event to save
* @return The saved event
*/
suspend fun save(veranstaltung: Veranstaltung): Veranstaltung
/**
* Deletes an event by its ID.
*
* @param id The unique identifier of the event to delete
* @return True if the event was deleted, false if not found
*/
suspend fun delete(id: Uuid): Boolean
/**
* Counts the number of active events.
*
* @return The number of active events
*/
suspend fun countActive(): Long
/**
* Counts events organized by a specific club.
*
* @param vereinId The ID of the organizing club
* @param activeOnly Whether to count only active events
* @return The number of events organized by the specified club
*/
suspend fun countByVeranstalterVereinId(vereinId: Uuid, activeOnly: Boolean = true): Long
}