docs: log session outcomes and apply enhancements across multiple components
Desktop CI — Headless Tests & Build / Compose Desktop — Tests (headless) & Build (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Has been cancelled
Desktop CI — Headless Tests & Build / Compose Desktop — Tests (headless) & Build (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Has been cancelled
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Has been cancelled
- **Docker Fixes:** Resolved failed builds for Gateway and Ping services by switching to `eclipse-temurin:21-jdk-alpine`, correcting Gradle configurations, and fixing cache mount paths. - **ZNS-Import Consul Registration:** Enabled Consul service discovery by updating `application.yaml` and `build.gradle.kts`. - **pgAdmin Provisioning:** Preconfigured the database server in `servers.json` and updated `dc-ops.yaml` for seamless setup. - **Postman Documentation:** Added a detailed Postman test guide covering environment setup, endpoint groups, and recommended test sequences. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -0,0 +1,960 @@
|
||||
# 🧪 Postman Tests — Vollständige Dokumentation
|
||||
|
||||
> **Stand:** 3. April 2026
|
||||
> **Erstellt von:** 👷 Backend Developer & 🧐 QA Specialist
|
||||
> **Collection-Datei:**
|
||||
`backend/infrastructure/gateway/src/main/resources/static/docs/postman/Meldestelle_API_Collection.json`
|
||||
|
||||
---
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Setup & Variablen](#1-setup--variablen)
|
||||
2. [Smoke-Tests: System & Health](#2-smoke-tests-system--health)
|
||||
3. [Ping Service](#3-ping-service)
|
||||
4. [Authentication Context](#4-authentication-context)
|
||||
5. [Master Data: Countries](#5-master-data-countries)
|
||||
6. [Horse Registry (Pferde)](#6-horse-registry-pferde)
|
||||
7. [ZNS Import Service](#7-zns-import-service)
|
||||
8. [Empfohlene Test-Reihenfolge](#8-empfohlene-test-reihenfolge)
|
||||
|
||||
---
|
||||
|
||||
## 1. Setup & Variablen
|
||||
|
||||
### Collection importieren
|
||||
|
||||
1. Postman öffnen → **Import** → Datei auswählen:
|
||||
```
|
||||
backend/infrastructure/gateway/src/main/resources/static/docs/postman/Meldestelle_API_Collection.json
|
||||
```
|
||||
2. Collection `Meldestelle API Collection` erscheint im linken Panel.
|
||||
|
||||
### Environment-Variablen anlegen
|
||||
|
||||
In Postman ein **Environment** `Meldestelle Local` anlegen mit folgenden Variablen:
|
||||
|
||||
| Variable | Initial Value | Beschreibung |
|
||||
|-------------|-------------------------|------------------------------------|
|
||||
| `baseUrl` | `http://localhost:8081` | API-Gateway (Haupt-Einstiegspunkt) |
|
||||
| `pingUrl` | `http://localhost:8082` | Ping-Service direkt (ohne Gateway) |
|
||||
| `znsUrl` | `http://localhost:8095` | ZNS-Import-Service direkt |
|
||||
| `authToken` | *(leer, wird befüllt)* | JWT-Token nach Login |
|
||||
| `horseId` | *(leer, wird befüllt)* | ID eines angelegten Pferdes |
|
||||
| `countryId` | *(leer, wird befüllt)* | ID eines angelegten Landes |
|
||||
| `horseId1` | *(leer)* | Für Batch-Delete Tests |
|
||||
| `horseId2` | *(leer)* | Für Batch-Delete Tests |
|
||||
|
||||
> ⚠️ **Wichtig:** Sicherstellen dass alle Services laufen bevor Tests gestartet werden (siehe Betriebsanleitung).
|
||||
|
||||
---
|
||||
|
||||
## 2. Smoke-Tests: System & Health
|
||||
|
||||
> **Zweck:** Schnell prüfen ob das API-Gateway und alle Services erreichbar sind. Immer zuerst ausführen!
|
||||
|
||||
---
|
||||
|
||||
### 2.1 API Gateway Info
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"service": "Meldestelle API Gateway",
|
||||
"version": "...",
|
||||
"status": "running"
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Bestätigt dass das Gateway läuft und auf Anfragen antwortet.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Health Check (Gateway)
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/health` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "UP"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 API Documentation
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|-------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — OpenAPI JSON-Dokumentation
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Swagger UI
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|-----------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/swagger` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Swagger HTML-Interface
|
||||
**Tipp:** Im Browser öffnen für interaktive API-Erkundung.
|
||||
|
||||
---
|
||||
|
||||
## 3. Ping Service
|
||||
|
||||
> **Zweck:** Funktionsfähigkeit des Ping-Service testen, Circuit Breaker und Sync-Funktionen validieren.
|
||||
> **Direkt-URL:** `{{pingUrl}}` = `http://localhost:8082`
|
||||
> **Via Gateway:** `{{baseUrl}}` = `http://localhost:8081`
|
||||
|
||||
---
|
||||
|
||||
### 3.1 Simple Ping
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/simple` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "pong",
|
||||
"timestamp": "2026-04-03T14:00:00+02:00",
|
||||
"service": "ping-service",
|
||||
"status": "simple"
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Einfachster Smoke-Test — bestätigt dass der Service läuft und die DB erreichbar ist.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Simple Ping via Gateway
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/ping/simple` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` (identisch wie 3.1)
|
||||
**Wozu:** Bestätigt dass das Gateway den Ping-Service korrekt routet (Service Discovery via Consul).
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Enhanced Ping (mit Circuit Breaker)
|
||||
|
||||
| Feld | Wert |
|
||||
|-----------------|-----------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/enhanced` |
|
||||
| **Auth** | Keine |
|
||||
| **Query-Param** | `simulate=false` (Standard) |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "enhanced pong",
|
||||
"timestamp": "...",
|
||||
"service": "ping-service",
|
||||
"status": "enhanced",
|
||||
"circuitBreakerStatus": "CLOSED"
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Bestätigt dass Resilience4j Circuit Breaker korrekt konfiguriert ist.
|
||||
|
||||
---
|
||||
|
||||
### 3.4 Enhanced Ping — Fehler simulieren
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|-------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/enhanced?simulate=true` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` mit Fallback-Response (kein 500-Fehler!)
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "fallback response",
|
||||
"status": "fallback",
|
||||
"circuitBreakerStatus": "OPEN",
|
||||
"error": "..."
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Bestätigt dass der Circuit Breaker Fallback greift (60% simulierte Fehlerrate). Der Service antwortet trotz
|
||||
Fehler mit einem sinnvollen Fallback.
|
||||
**Mehrfach ausführen:** Nach ~5 Anfragen mit `simulate=true` öffnet der Circuit Breaker.
|
||||
|
||||
---
|
||||
|
||||
### 3.5 Public Ping (kein Auth erforderlich)
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/public` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
**Wozu:** Bestätigt dass der `/ping/public`-Endpunkt ohne JWT-Token erreichbar ist (Security-Konfiguration).
|
||||
|
||||
---
|
||||
|
||||
### 3.6 Secure Ping (Auth erforderlich)
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/secure` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Mit gültigem Token:** `200 OK`
|
||||
**Ohne Token:** `401 Unauthorized`
|
||||
**Wozu:** Bestätigt dass JWT-Authentifizierung korrekt erzwungen wird.
|
||||
|
||||
---
|
||||
|
||||
### 3.7 Sync Pings (seit Timestamp)
|
||||
|
||||
| Feld | Wert |
|
||||
|-----------------|-----------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/sync` |
|
||||
| **Auth** | Keine |
|
||||
| **Query-Param** | `since=0` (alle Pings seit Epoch) |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "...",
|
||||
"message": "pong",
|
||||
"timestamp": "...",
|
||||
"lamportClock": 1
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Wozu:** Testet den LAN-Sync-Endpunkt (Lamport-Uhren, Event-Sourcing Light). `since` ist ein Unix-Timestamp in
|
||||
Millisekunden.
|
||||
|
||||
---
|
||||
|
||||
### 3.8 Ping Service Health
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{pingUrl}}/ping/health` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "up",
|
||||
"timestamp": "...",
|
||||
"service": "ping-service",
|
||||
"healthy": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Authentication Context
|
||||
|
||||
> **Zweck:** Benutzer-Registrierung, Login und Profilverwaltung über Keycloak testen.
|
||||
> **Reihenfolge:** Zuerst registrieren → dann einloggen → Token in `{{authToken}}` speichern.
|
||||
|
||||
---
|
||||
|
||||
### 4.1 User Registration
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{baseUrl}}/auth/register` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "test@example.com",
|
||||
"password": "SecurePassword123!",
|
||||
"firstName": "Test",
|
||||
"lastName": "User",
|
||||
"phoneNumber": "+43123456789"
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `201 Created`
|
||||
|
||||
```json
|
||||
{
|
||||
"userId": "uuid-...",
|
||||
"email": "test@example.com",
|
||||
"message": "Registrierung erfolgreich"
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Legt einen neuen Benutzer in Keycloak an.
|
||||
|
||||
---
|
||||
|
||||
### 4.2 User Login
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{baseUrl}}/auth/login` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "test@example.com",
|
||||
"password": "SecurePassword123!"
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "eyJhbGci...",
|
||||
"refreshToken": "...",
|
||||
"expiresIn": 300
|
||||
}
|
||||
```
|
||||
|
||||
> **⚡ Tipp:** Postman-Test-Script einfügen um Token automatisch zu speichern:
|
||||
> ```javascript
|
||||
> var json = pm.response.json();
|
||||
> pm.environment.set("authToken", json.accessToken);
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Get User Profile
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/auth/profile` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"userId": "...",
|
||||
"email": "test@example.com",
|
||||
"firstName": "Test",
|
||||
"lastName": "User"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.4 Update User Profile
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `PUT` |
|
||||
| **URL** | `{{baseUrl}}/auth/profile` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"firstName": "Updated",
|
||||
"lastName": "User",
|
||||
"phoneNumber": "+43987654321"
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — aktualisierte Profildaten
|
||||
|
||||
---
|
||||
|
||||
### 4.5 Change Password
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{baseUrl}}/auth/change-password` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"currentPassword": "SecurePassword123!",
|
||||
"newPassword": "NewSecurePassword456!"
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
**Fehlerfall (falsches Passwort):** `400 Bad Request`
|
||||
|
||||
---
|
||||
|
||||
## 5. Master Data: Countries
|
||||
|
||||
> **Zweck:** Länderstammdaten verwalten. Diese sind Voraussetzung für Pferde- und Reiter-Datensätze.
|
||||
> **Basis-URL:** `{{baseUrl}}/api/masterdata/countries`
|
||||
> **Hinweis:** GET-Endpunkte sind ohne Auth zugänglich; POST/PUT/DELETE benötigen `{{authToken}}`.
|
||||
|
||||
---
|
||||
|
||||
### 5.1 Get All Countries
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Array aller Länder (inkl. inaktive)
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Get Active Countries
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|-----------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries/active` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Nur Länder mit `istAktiv: true`
|
||||
**Wozu:** Für Dropdown-Listen in der Desktop-App (nur aktive Länder anzeigen).
|
||||
|
||||
---
|
||||
|
||||
### 5.3 Get Country by ID
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|------------------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Einzelnes Land
|
||||
**Fehlerfall:** `404 Not Found`
|
||||
|
||||
---
|
||||
|
||||
### 5.4 Get Country by ISO Code
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|-----------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries/iso/AT` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "...",
|
||||
"isoAlpha2Code": "AT",
|
||||
"nameDeutsch": "Österreich",
|
||||
"istEuMitglied": true,
|
||||
"istAktiv": true
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Österreich ist das primäre Land — dieser Test prüft ob die Stammdaten korrekt befüllt sind.
|
||||
|
||||
---
|
||||
|
||||
### 5.5 Create Country
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"isoAlpha2Code": "TS",
|
||||
"isoAlpha3Code": "TST",
|
||||
"isoNumerischerCode": "999",
|
||||
"nameDeutsch": "Testland",
|
||||
"nameEnglisch": "Testland",
|
||||
"istEuMitglied": false,
|
||||
"istEwrMitglied": false,
|
||||
"istAktiv": true,
|
||||
"sortierReihenfolge": 999
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `201 Created`
|
||||
|
||||
> **⚡ Tipp:** `countryId` aus der Antwort in Environment-Variable speichern:
|
||||
> ```javascript
|
||||
> var json = pm.response.json();
|
||||
> pm.environment.set("countryId", json.id);
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
### 5.6 Update Country
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|------------------------------------------------------|
|
||||
| **Methode** | `PUT` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"isoAlpha2Code": "TS",
|
||||
"isoAlpha3Code": "TST",
|
||||
"isoNumerischerCode": "999",
|
||||
"nameDeutsch": "Updated Testland",
|
||||
"nameEnglisch": "Updated Testland",
|
||||
"istEuMitglied": false,
|
||||
"istEwrMitglied": false,
|
||||
"istAktiv": true,
|
||||
"sortierReihenfolge": 999
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
---
|
||||
|
||||
### 5.7 Delete Country
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|------------------------------------------------------|
|
||||
| **Methode** | `DELETE` |
|
||||
| **URL** | `{{baseUrl}}/api/masterdata/countries/{{countryId}}` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `204 No Content`
|
||||
**Fehlerfall (nicht gefunden):** `404 Not Found`
|
||||
|
||||
---
|
||||
|
||||
## 6. Horse Registry (Pferde)
|
||||
|
||||
> **Zweck:** Pferde-Stammdaten verwalten (CRUD).
|
||||
> **⚠️ Hinweis Tabellen-Name:** In der Datenbank heißt die Tabelle `horse` (englisch), nicht `pferd`.
|
||||
> **Basis-URL:** `{{baseUrl}}/api/horses`
|
||||
|
||||
---
|
||||
|
||||
### 6.1 Get All Horses
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Array aller Pferde
|
||||
**Nach ZNS-Import:** Hier erscheinen alle importierten Pferde.
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Get Active Horses
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/active` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — Nur Pferde mit `istAktiv: true`
|
||||
|
||||
---
|
||||
|
||||
### 6.3 Get Horse by ID
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "uuid-...",
|
||||
"pferdeName": "Amadeus",
|
||||
"geschlecht": "WALLACH",
|
||||
"geburtsdatum": "2020-05-15",
|
||||
"rasse": "Warmblut",
|
||||
"farbe": "Braun",
|
||||
"stockmass": 165,
|
||||
"istAktiv": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6.4 Search Horses by Name
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/search` |
|
||||
| **Query** | `name=Test` (Suchbegriff), `limit=10` (max.) |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — gefilterte Pferde-Liste
|
||||
**Wozu:** Echtzeit-Suche in der Desktop-App. Testen mit einem Namen aus dem ZNS-Import.
|
||||
|
||||
---
|
||||
|
||||
### 6.5 Get Horses by Owner
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|--------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/owner/{{ownerId}}` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK` — alle Pferde eines bestimmten Besitzers
|
||||
|
||||
---
|
||||
|
||||
### 6.6 Create Horse
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{baseUrl}}/api/horses` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"pferdeName": "Test Horse",
|
||||
"geschlecht": "WALLACH",
|
||||
"geburtsdatum": "2020-05-15",
|
||||
"rasse": "Warmblut",
|
||||
"farbe": "Braun",
|
||||
"zuechterName": "Test Breeder",
|
||||
"stockmass": 165,
|
||||
"istAktiv": true,
|
||||
"bemerkungen": "Test horse for API demonstration"
|
||||
}
|
||||
```
|
||||
|
||||
**Gültige Werte für `geschlecht`:** `WALLACH`, `STUTE`, `HENGST`
|
||||
|
||||
**Erwartete Antwort:** `201 Created`
|
||||
|
||||
> **⚡ Tipp:** `horseId` automatisch speichern:
|
||||
> ```javascript
|
||||
> var json = pm.response.json();
|
||||
> pm.environment.set("horseId", json.id);
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
### 6.7 Update Horse
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `PUT` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"pferdeName": "Updated Test Horse",
|
||||
"geschlecht": "WALLACH",
|
||||
"geburtsdatum": "2020-05-15",
|
||||
"rasse": "Warmblut",
|
||||
"farbe": "Dunkelbraun",
|
||||
"zuechterName": "Updated Test Breeder",
|
||||
"stockmass": 167,
|
||||
"istAktiv": true,
|
||||
"bemerkungen": "Updated test horse for API demonstration"
|
||||
}
|
||||
```
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
---
|
||||
|
||||
### 6.8 Delete Horse
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `DELETE` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/{{horseId}}` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `204 No Content`
|
||||
|
||||
---
|
||||
|
||||
### 6.9 Batch Delete Horses
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `DELETE` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/batch` |
|
||||
| **Header** | `Content-Type: application/json` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"horseIds": ["{{horseId1}}", "{{horseId2}}"],
|
||||
"forceDelete": false
|
||||
}
|
||||
```
|
||||
|
||||
**`forceDelete: false`** → Nur löschen wenn keine Abhängigkeiten vorhanden
|
||||
**`forceDelete: true`** → Auch bei Abhängigkeiten löschen (⚠️ Vorsicht!)
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
---
|
||||
|
||||
### 6.10 Get Horse Statistics
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|---------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{baseUrl}}/api/horses/stats` |
|
||||
| **Header** | `Authorization: Bearer {{authToken}}` |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 42,
|
||||
"active": 38,
|
||||
"inactive": 4,
|
||||
"byGeschlecht": {
|
||||
"WALLACH": 20,
|
||||
"STUTE": 18,
|
||||
"HENGST": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Wozu:** Schnelle Übersicht über den Datenbestand nach dem ZNS-Import.
|
||||
|
||||
---
|
||||
|
||||
## 7. ZNS Import Service
|
||||
|
||||
> **Zweck:** ZNS-Daten (Reiter, Pferde, Vereine, Funktionäre) aus einer `.zip`/`.dat`-Datei importieren.
|
||||
> **Direkt-URL:** `{{znsUrl}}` = `http://localhost:8095`
|
||||
> **Basis-Pfad:** `/api/v1/import/zns`
|
||||
|
||||
---
|
||||
|
||||
### 7.1 ZNS Import starten
|
||||
|
||||
| Feld | Wert |
|
||||
|--------------|------------------------------------------|
|
||||
| **Methode** | `POST` |
|
||||
| **URL** | `{{znsUrl}}/api/v1/import/zns` |
|
||||
| **Body-Typ** | `form-data` |
|
||||
| **Key** | `file` (Type: **File**) |
|
||||
| **Value** | ZNS-Datei auswählen (`.zip` oder `.dat`) |
|
||||
|
||||
**Schritt-für-Schritt in Postman:**
|
||||
|
||||
1. Methode: `POST`
|
||||
2. URL: `http://localhost:8095/api/v1/import/zns`
|
||||
3. Tab **Body** → **form-data**
|
||||
4. Key: `file` → Typ auf **File** umstellen (Dropdown neben dem Key-Feld)
|
||||
5. Value: ZNS-Datei auswählen
|
||||
6. **Send** klicken
|
||||
|
||||
**Erwartete Antwort:** `202 Accepted`
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "abc-123-def-456",
|
||||
"status": "STARTED",
|
||||
"message": "Import gestartet",
|
||||
"startedAt": "2026-04-03T14:00:00+02:00"
|
||||
}
|
||||
```
|
||||
|
||||
> **⚡ Tipp:** `jobId` automatisch speichern:
|
||||
> ```javascript
|
||||
> var json = pm.response.json();
|
||||
> pm.environment.set("znsJobId", json.jobId);
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
### 7.2 ZNS Import-Status abfragen
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|----------------------------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{znsUrl}}/api/v1/import/zns/{{znsJobId}}/status` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Antwort während Import:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "abc-123-def-456",
|
||||
"status": "IN_PROGRESS",
|
||||
"processedRecords": 150,
|
||||
"totalRecords": 500,
|
||||
"progressPercent": 30,
|
||||
"startedAt": "2026-04-03T14:00:00+02:00"
|
||||
}
|
||||
```
|
||||
|
||||
**Antwort nach Abschluss:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": "abc-123-def-456",
|
||||
"status": "COMPLETED",
|
||||
"processedRecords": 500,
|
||||
"totalRecords": 500,
|
||||
"progressPercent": 100,
|
||||
"importedReiter": 200,
|
||||
"importedPferde": 180,
|
||||
"importedVereine": 30,
|
||||
"importedFunktionaere": 90,
|
||||
"startedAt": "2026-04-03T14:00:00+02:00",
|
||||
"completedAt": "2026-04-03T14:01:30+02:00"
|
||||
}
|
||||
```
|
||||
|
||||
**Mögliche Status-Werte:**
|
||||
|
||||
| Status | Bedeutung |
|
||||
|---------------|----------------------------------------|
|
||||
| `STARTED` | Job wurde angenommen, noch nicht aktiv |
|
||||
| `IN_PROGRESS` | Import läuft gerade |
|
||||
| `COMPLETED` | Import erfolgreich abgeschlossen |
|
||||
| `FAILED` | Import fehlgeschlagen (Fehlerdetails) |
|
||||
|
||||
**Wozu:** Status pollen bis `COMPLETED` — dann Daten in pgAdmin oder Desktop-App prüfen.
|
||||
|
||||
---
|
||||
|
||||
### 7.3 ZNS Import Health-Check
|
||||
|
||||
| Feld | Wert |
|
||||
|-------------|------------------------------|
|
||||
| **Methode** | `GET` |
|
||||
| **URL** | `{{znsUrl}}/actuator/health` |
|
||||
| **Auth** | Keine |
|
||||
|
||||
**Erwartete Antwort:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "UP",
|
||||
"components": {
|
||||
"db": { "status": "UP" },
|
||||
"diskSpace": { "status": "UP" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**⚠️ Consul-Check:** Nach dem Neustart des ZNS-Service sollte er im Consul-UI unter http://localhost:8500 unter dem
|
||||
Namen `zns-import-service` erscheinen.
|
||||
|
||||
---
|
||||
|
||||
## 8. Empfohlene Test-Reihenfolge
|
||||
|
||||
### Schnell-Smoke-Test (5 Minuten)
|
||||
|
||||
```
|
||||
1. GET {{pingUrl}}/ping/simple → "pong" ✓
|
||||
2. GET {{baseUrl}}/health → "UP" ✓
|
||||
3. GET {{znsUrl}}/actuator/health → "UP" ✓
|
||||
4. GET {{baseUrl}}/api/masterdata/countries/iso/AT → Österreich ✓
|
||||
```
|
||||
|
||||
### Vollständiger Integrations-Test (heute, ZNS-Import)
|
||||
|
||||
```
|
||||
1. GET {{pingUrl}}/ping/simple → Smoke-Test
|
||||
2. GET {{pingUrl}}/ping/enhanced → Circuit Breaker CLOSED
|
||||
3. GET {{pingUrl}}/ping/enhanced?simulate=true → Fallback greift
|
||||
4. POST {{baseUrl}}/auth/login → Token speichern
|
||||
5. GET {{baseUrl}}/api/masterdata/countries/iso/AT → Stammdaten vorhanden
|
||||
6. GET {{baseUrl}}/api/horses → (leer vor Import)
|
||||
7. GET {{znsUrl}}/actuator/health → ZNS bereit
|
||||
8. POST {{znsUrl}}/api/v1/import/zns → ZNS-Datei hochladen → jobId speichern
|
||||
9. GET {{znsUrl}}/api/v1/import/zns/{{znsJobId}}/status → Status pollen bis COMPLETED
|
||||
10. GET {{baseUrl}}/api/horses → Pferde jetzt befüllt ✓
|
||||
11. GET {{baseUrl}}/api/horses/stats → Statistiken prüfen
|
||||
12. GET {{baseUrl}}/api/horses/search?name=... → Suche testen
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Anhang: Alle URLs auf einen Blick
|
||||
|
||||
| Service | URL | Verwendung |
|
||||
|----------------|-----------------------|--------------------------|
|
||||
| API-Gateway | http://localhost:8081 | Haupt-Einstiegspunkt |
|
||||
| Ping (direkt) | http://localhost:8082 | Ping-Endpunkte direkt |
|
||||
| ZNS-Import | http://localhost:8095 | Import-Endpunkte |
|
||||
| Keycloak Admin | http://localhost:8180 | Auth-Verwaltung |
|
||||
| Consul UI | http://localhost:8500 | Service-Discovery prüfen |
|
||||
| Zipkin | http://localhost:9411 | Traces nachverfolgen |
|
||||
| pgAdmin | http://localhost:8888 | DB-Inhalte prüfen |
|
||||
| Mailpit | http://localhost:8025 | E-Mail-Mock |
|
||||
Reference in New Issue
Block a user