65a0084f91
- Detaillierter Plan zur Migration von alter zu neuer Modulstruktur - Umfasst Überführung von shared-kernel zu core-Modulen - Definiert Migration von Fachdomänen zu bounded contexts: * master-data → masterdata-Module * member-management → members-Module * horse-registry → horses-Module * event-management → events-Module - Beschreibt Verlagerung von api-gateway zu infrastructure/gateway - Strukturiert nach Domain-driven Design Prinzipien - Berücksichtigt Clean Architecture Layering (domain, application, infrastructure, api)
334 lines
9.4 KiB
Markdown
334 lines
9.4 KiB
Markdown
# Members Module
|
|
|
|
## Überblick
|
|
|
|
Das Members-Modul ist eine umfassende Lösung zur Verwaltung von Mitgliedern für Pferdesportorganisationen. Es implementiert eine saubere Architektur mit Domain-Driven Design und bietet vollständige CRUD-Operationen sowie erweiterte Geschäftslogik für die Mitgliederverwaltung.
|
|
|
|
## Funktionalität
|
|
|
|
### Verwaltete Entität
|
|
|
|
#### Mitglied (Member)
|
|
- **Persönliche Informationen**: Vor- und Nachname, E-Mail, Telefon, Geburtsdatum
|
|
- **Mitgliedschaftsinformationen**: Mitgliedsnummer, Start-/Enddatum, Aktivitätsstatus
|
|
- **Zusätzliche Informationen**: Adresse, Notfallkontakt
|
|
- **Audit-Felder**: Erstellungs- und Aktualisierungszeitstempel
|
|
- **Geschäftslogik**: Validierung, Mitgliedschaftsgültigkeit, Vollständiger Name
|
|
|
|
### Geschäftsoperationen
|
|
|
|
Das Modul bietet 18+ spezialisierte Repository-Operationen:
|
|
|
|
#### Basis-CRUD-Operationen
|
|
- `findById(id)` - Mitglied nach UUID suchen
|
|
- `save(member)` - Mitglied speichern (erstellen/aktualisieren)
|
|
- `delete(id)` - Mitglied löschen
|
|
|
|
#### Such-Operationen
|
|
- `findByMembershipNumber(number)` - Nach Mitgliedsnummer suchen
|
|
- `findByEmail(email)` - Nach E-Mail-Adresse suchen
|
|
- `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung)
|
|
- `findAllActive(limit, offset)` - Alle aktiven Mitglieder
|
|
- `findAll(limit, offset)` - Alle Mitglieder (aktiv und inaktiv)
|
|
|
|
#### Datumsbasierte Abfragen
|
|
- `findByMembershipStartDateRange(start, end)` - Mitglieder nach Startdatum-Bereich
|
|
- `findByMembershipEndDateRange(start, end)` - Mitglieder nach Enddatum-Bereich
|
|
- `findMembersWithExpiringMembership(daysAhead)` - Mitglieder mit ablaufender Mitgliedschaft
|
|
|
|
#### Validierungs-Operationen
|
|
- `existsByMembershipNumber(number, excludeId)` - Prüfung auf doppelte Mitgliedsnummer
|
|
- `existsByEmail(email, excludeId)` - Prüfung auf doppelte E-Mail-Adresse
|
|
|
|
#### Zähl-Operationen
|
|
- `countActive()` - Anzahl aktiver Mitglieder
|
|
- `countAll()` - Gesamtanzahl aller Mitglieder
|
|
|
|
## Architektur
|
|
|
|
Das Modul folgt der Clean Architecture mit klarer Trennung der Verantwortlichkeiten:
|
|
|
|
```
|
|
members/
|
|
├── members-domain/ # Domain Layer
|
|
│ ├── model/ # Domain Models
|
|
│ │ └── Member.kt # Mitglied-Entität mit Geschäftslogik
|
|
│ ├── repository/ # Repository Interfaces
|
|
│ │ └── MemberRepository.kt # 18+ Geschäftsoperationen
|
|
│ └── events/ # Domain Events
|
|
│ └── MemberEvents.kt # Mitgliedschafts-Events
|
|
├── members-application/ # Application Layer
|
|
│ └── usecase/ # Use Cases
|
|
│ └── FindExpiringMembershipsUseCase.kt
|
|
├── members-infrastructure/ # Infrastructure Layer
|
|
│ ├── persistence/ # Database Implementation
|
|
│ │ ├── MemberRepositoryImpl.kt
|
|
│ │ └── MemberTable.kt
|
|
│ └── repository/ # Alternative Implementations
|
|
│ └── InMemoryMemberRepository.kt
|
|
├── members-api/ # API Layer
|
|
│ └── rest/ # REST Controllers
|
|
│ └── MemberController.kt
|
|
└── members-service/ # Service Layer
|
|
├── MembersServiceApplication.kt
|
|
└── test/ # Integration Tests
|
|
└── MemberServiceIntegrationTest.kt
|
|
```
|
|
|
|
### Domain Layer
|
|
- **1 Domain Model** mit reichhaltiger Geschäftslogik
|
|
- **1 Repository Interface** mit 18+ Geschäftsoperationen
|
|
- **Domain Events** für Mitgliedschaftsänderungen
|
|
- **Keine Abhängigkeiten** zu anderen Layern
|
|
|
|
### Application Layer
|
|
- **Use Cases** für komplexe Geschäftsoperationen
|
|
- **Orchestrierung** von Domain-Services
|
|
- **Anwendungslogik** ohne UI-Abhängigkeiten
|
|
|
|
### Infrastructure Layer
|
|
- **Datenbankzugriff** mit Exposed ORM
|
|
- **Repository-Implementierung** mit PostgreSQL
|
|
- **In-Memory-Repository** für Tests
|
|
- **Datenbankschema** und Migrationen
|
|
|
|
### API Layer
|
|
- **REST-Controller** für HTTP-Endpunkte
|
|
- **DTO-Mapping** zwischen Domain und API
|
|
- **Validierung** und Fehlerbehandlung
|
|
|
|
### Service Layer
|
|
- **Spring Boot Anwendung**
|
|
- **Dependency Injection** Konfiguration
|
|
- **Integrationstests**
|
|
|
|
## Domain Model Details
|
|
|
|
### Member-Entität
|
|
|
|
```kotlin
|
|
data class Member(
|
|
val memberId: Uuid,
|
|
|
|
// Persönliche Informationen
|
|
var firstName: String,
|
|
var lastName: String,
|
|
var email: String,
|
|
var phone: String? = null,
|
|
var dateOfBirth: LocalDate? = null,
|
|
|
|
// Mitgliedschaftsinformationen
|
|
var membershipNumber: String,
|
|
var membershipStartDate: LocalDate,
|
|
var membershipEndDate: LocalDate? = null,
|
|
var isActive: Boolean = true,
|
|
|
|
// Zusätzliche Informationen
|
|
var address: String? = null,
|
|
var emergencyContact: String? = null,
|
|
|
|
// Audit-Felder
|
|
val createdAt: Instant,
|
|
var updatedAt: Instant
|
|
)
|
|
```
|
|
|
|
### Geschäftslogik-Methoden
|
|
|
|
- `getFullName()` - Vollständiger Name des Mitglieds
|
|
- `isMembershipValid()` - Prüfung der Mitgliedschaftsgültigkeit
|
|
- `validate()` - Datenvalidierung mit Fehlerliste
|
|
- `withUpdatedTimestamp()` - Kopie mit aktualisiertem Zeitstempel
|
|
|
|
## Repository-Operationen
|
|
|
|
### Erweiterte Such-Features
|
|
|
|
```kotlin
|
|
// Mitglieder mit ablaufender Mitgliedschaft finden
|
|
val expiringMembers = memberRepository.findMembersWithExpiringMembership(30)
|
|
|
|
// Mitglieder nach Datumsbereich suchen
|
|
val newMembers = memberRepository.findByMembershipStartDateRange(
|
|
startDate = LocalDate(2024, 1, 1),
|
|
endDate = LocalDate(2024, 12, 31)
|
|
)
|
|
|
|
// Namenssuche mit Teilübereinstimmung
|
|
val searchResults = memberRepository.findByName("Schmidt", limit = 10)
|
|
```
|
|
|
|
### Validierung und Duplikatsprüfung
|
|
|
|
```kotlin
|
|
// Prüfung auf doppelte Mitgliedsnummer
|
|
val numberExists = memberRepository.existsByMembershipNumber("M2024001")
|
|
|
|
// Prüfung auf doppelte E-Mail (mit Ausschluss für Updates)
|
|
val emailExists = memberRepository.existsByEmail(
|
|
email = "max@example.com",
|
|
excludeMemberId = existingMember.memberId
|
|
)
|
|
```
|
|
|
|
## Use Cases
|
|
|
|
### FindExpiringMembershipsUseCase
|
|
|
|
Findet Mitglieder mit ablaufenden Mitgliedschaften und kann automatische Benachrichtigungen auslösen.
|
|
|
|
```kotlin
|
|
class FindExpiringMembershipsUseCase(
|
|
private val memberRepository: MemberRepository
|
|
) {
|
|
suspend fun execute(daysAhead: Int = 30): List<Member> {
|
|
return memberRepository.findMembersWithExpiringMembership(daysAhead)
|
|
}
|
|
}
|
|
```
|
|
|
|
## API-Endpunkte
|
|
|
|
Das Members-Modul stellt REST-Endpunkte über den MemberController bereit:
|
|
|
|
- `GET /api/members` - Alle aktiven Mitglieder abrufen
|
|
- `GET /api/members/{id}` - Mitglied nach ID abrufen
|
|
- `GET /api/members/search?name={name}` - Mitglieder nach Namen suchen
|
|
- `GET /api/members/expiring?days={days}` - Mitglieder mit ablaufender Mitgliedschaft
|
|
- `POST /api/members` - Neues Mitglied erstellen
|
|
- `PUT /api/members/{id}` - Mitglied aktualisieren
|
|
- `DELETE /api/members/{id}` - Mitglied löschen
|
|
|
|
## Konfiguration
|
|
|
|
### Datenbankschema
|
|
|
|
Das Modul verwendet eine `members`-Tabelle mit folgenden Spalten:
|
|
- `member_id` (UUID, Primary Key)
|
|
- `first_name`, `last_name`, `email` (Required)
|
|
- `phone`, `date_of_birth` (Optional)
|
|
- `membership_number` (Unique)
|
|
- `membership_start_date`, `membership_end_date`
|
|
- `is_active` (Boolean)
|
|
- `address`, `emergency_contact` (Optional)
|
|
- `created_at`, `updated_at` (Timestamps)
|
|
|
|
### Service-Konfiguration
|
|
|
|
```yaml
|
|
# application.yml
|
|
members:
|
|
service:
|
|
name: members-service
|
|
port: 8082
|
|
database:
|
|
url: jdbc:postgresql://localhost:5432/meldestelle
|
|
table: members
|
|
```
|
|
|
|
## Tests
|
|
|
|
### Integration Tests
|
|
|
|
Das Modul enthält umfassende Integrationstests:
|
|
|
|
```kotlin
|
|
@Test
|
|
fun `should find members with expiring membership`() {
|
|
// Test-Implementierung für ablaufende Mitgliedschaften
|
|
}
|
|
|
|
@Test
|
|
fun `should validate unique membership number`() {
|
|
// Test für Eindeutigkeit der Mitgliedsnummer
|
|
}
|
|
```
|
|
|
|
### Test-Datenbank
|
|
|
|
Verwendet H2 In-Memory-Datenbank für Tests mit automatischem Schema-Setup.
|
|
|
|
## Deployment
|
|
|
|
### Docker
|
|
|
|
```dockerfile
|
|
FROM openjdk:21-jre-slim
|
|
COPY members-service.jar app.jar
|
|
EXPOSE 8082
|
|
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
|
```
|
|
|
|
### Kubernetes
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: members-service
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: members-service
|
|
template:
|
|
spec:
|
|
containers:
|
|
- name: members-service
|
|
image: meldestelle/members-service:latest
|
|
ports:
|
|
- containerPort: 8082
|
|
```
|
|
|
|
## Monitoring
|
|
|
|
### Metriken
|
|
|
|
- Anzahl aktiver Mitglieder
|
|
- Anzahl ablaufender Mitgliedschaften
|
|
- API-Response-Zeiten
|
|
- Datenbankverbindungs-Pool
|
|
|
|
### Health Checks
|
|
|
|
- Datenbankverbindung
|
|
- Service-Verfügbarkeit
|
|
- Speicherverbrauch
|
|
|
|
## Entwicklung
|
|
|
|
### Lokale Entwicklung
|
|
|
|
```bash
|
|
# Service starten
|
|
./gradlew :members:members-service:bootRun
|
|
|
|
# Tests ausführen
|
|
./gradlew :members:test
|
|
|
|
# Integration Tests
|
|
./gradlew :members:members-service:test
|
|
```
|
|
|
|
### Code-Qualität
|
|
|
|
- **Kotlin Coding Standards**
|
|
- **100% Test Coverage** für Domain Layer
|
|
- **Integration Tests** für alle Use Cases
|
|
- **API-Dokumentation** mit OpenAPI
|
|
|
|
## Zukünftige Erweiterungen
|
|
|
|
1. **Mitgliedschaftstypen** - Verschiedene Mitgliedschaftskategorien
|
|
2. **Beitragsverwaltung** - Integration mit Zahlungssystem
|
|
3. **Mitgliedschaftshistorie** - Tracking von Änderungen
|
|
4. **Bulk-Operationen** - Massenimport/-export
|
|
5. **Benachrichtigungen** - Automatische E-Mail-Benachrichtigungen
|
|
6. **Reporting** - Mitgliedschaftsstatistiken und Reports
|
|
|
|
---
|
|
|
|
**Letzte Aktualisierung**: 25. Juli 2025
|
|
|
|
Für weitere Informationen zur Gesamtarchitektur siehe [README.md](../README.md).
|