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
@@ -0,0 +1,41 @@
package at.mocode.core.domain.event
import java.time.Instant
import java.util.UUID
/**
* Interface for all domain events in the system.
* Domain events represent something that happened in the domain that domain experts care about.
*/
interface DomainEvent {
/**
* Unique identifier for this event instance.
*/
val eventId: UUID
/**
* Timestamp when the event occurred.
*/
val timestamp: Instant
/**
* Identifier of the aggregate that the event belongs to.
*/
val aggregateId: UUID
/**
* Version of the aggregate after the event was applied.
*/
val version: Long
}
/**
* Base implementation of the DomainEvent interface.
* Provides default implementations for common properties.
*/
abstract class BaseDomainEvent(
override val eventId: UUID = UUID.randomUUID(),
override val timestamp: Instant = Instant.now(),
override val aggregateId: UUID,
override val version: Long
) : DomainEvent
@@ -0,0 +1,96 @@
package at.mocode.core.domain.model
import at.mocode.core.domain.serialization.KotlinInstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer
import com.benasher44.uuid.Uuid
import kotlinx.datetime.Instant
import kotlinx.serialization.Serializable
/**
* Base DTO interface for all data transfer objects
*/
interface BaseDto
/**
* Base DTO for entities with ID and timestamps
*/
@Serializable
abstract class EntityDto : BaseDto {
@Serializable(with = UuidSerializer::class)
abstract val id: Uuid
@Serializable(with = KotlinInstantSerializer::class)
abstract val createdAt: Instant
@Serializable(with = KotlinInstantSerializer::class)
abstract val updatedAt: Instant
}
/**
* Standard API response wrapper
*/
@Serializable
data class ApiResponse<T>(
val success: Boolean,
val data: T? = null,
val error: ErrorDto? = null,
val message: String? = null
) : BaseDto {
companion object {
/**
* Creates a successful API response with data
*/
fun <T> success(data: T, message: String? = null): ApiResponse<T> {
return ApiResponse(
success = true,
data = data,
message = message
)
}
/**
* Creates an error API response
*/
fun <T> error(message: String, code: String = "ERROR", details: Map<String, String>? = null): ApiResponse<T> {
return ApiResponse(
success = false,
error = ErrorDto(
code = code,
message = message,
details = details
)
)
}
}
}
/**
* Error information DTO
*/
@Serializable
data class ErrorDto(
val code: String,
val message: String,
val details: Map<String, String>? = null
) : BaseDto
/**
* Pagination information
*/
@Serializable
data class PaginationDto(
val page: Int,
val size: Int,
val total: Long,
val totalPages: Int
) : BaseDto
/**
* Paginated response wrapper
*/
@Serializable
data class PagedResponse<T>(
val data: List<T>,
val pagination: PaginationDto
) : BaseDto
@@ -0,0 +1,90 @@
package at.mocode.core.domain.model
import kotlinx.serialization.Serializable
/**
* Data source enumeration - indicates where data originated from
*/
@Serializable
enum class DatenQuelleE { OEPS_ZNS, MANUELL }
/**
* Horse gender enumeration
*/
@Serializable
enum class PferdeGeschlechtE {
HENGST, STUTE, WALLACH, UNBEKANNT
}
/**
* Person gender enumeration
*/
@Serializable
enum class GeschlechtE { M, W, D, UNBEKANNT }
/**
* Sport discipline enumeration
*/
@Serializable
enum class SparteE { DRESSUR, SPRINGEN, VIELSEITIGKEIT, FAHREN, VOLTIGIEREN, WESTERN, DISTANZ, ISLAND, PFERDESPORT_SPIEL, BASIS, KOMBINIERT, SONSTIGES }
/**
* Venue/place type enumeration
*/
@Serializable
enum class PlatzTypE { AUSTRAGUNG, VORBEREITUNG, LONGIEREN, SONSTIGES }
/**
* User role enumeration for member management
*/
@Serializable
enum class RolleE {
ADMIN, // System administrator
VEREINS_ADMIN, // Club administrator
FUNKTIONAER, // Official/functionary
REITER, // Rider
TRAINER, // Trainer
RICHTER, // Judge
TIERARZT, // Veterinarian
ZUSCHAUER, // Spectator
GAST // Guest
}
/**
* Permission enumeration for access control
*/
@Serializable
enum class BerechtigungE {
// Person management
PERSON_READ,
PERSON_CREATE,
PERSON_UPDATE,
PERSON_DELETE,
// Club management
VEREIN_READ,
VEREIN_CREATE,
VEREIN_UPDATE,
VEREIN_DELETE,
// Event management
VERANSTALTUNG_READ,
VERANSTALTUNG_CREATE,
VERANSTALTUNG_UPDATE,
VERANSTALTUNG_DELETE,
// Horse management
PFERD_READ,
PFERD_CREATE,
PFERD_UPDATE,
PFERD_DELETE,
// Master data management
STAMMDATEN_READ,
STAMMDATEN_UPDATE,
// System administration
SYSTEM_ADMIN,
BENUTZER_VERWALTEN,
ROLLEN_VERWALTEN
}
@@ -0,0 +1,59 @@
package at.mocode.core.domain.serialization
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuidFrom
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* Serializer for UUID values
*/
object UuidSerializer : KSerializer<Uuid> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Uuid) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): Uuid = uuidFrom(decoder.decodeString())
}
/**
* Serializer for Instant values
*/
object KotlinInstantSerializer : KSerializer<Instant> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Instant) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): Instant = Instant.parse(decoder.decodeString())
}
/**
* Serializer for LocalDate values
*/
object KotlinLocalDateSerializer : KSerializer<LocalDate> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDate", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDate) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): LocalDate = LocalDate.parse(decoder.decodeString())
}
/**
* Serializer for LocalDateTime values
*/
object KotlinLocalDateTimeSerializer : KSerializer<LocalDateTime> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDateTime) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): LocalDateTime = LocalDateTime.parse(decoder.decodeString())
}
/**
* Serializer for LocalTime values
*/
object KotlinLocalTimeSerializer : KSerializer<LocalTime> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("LocalTime", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalTime) = encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): LocalTime = LocalTime.parse(decoder.decodeString())
}