Update AGENTS.md and add project documentation and skills
This commit is contained in:
@@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
name: testing
|
||||||
|
description: Write und ausführen von Tests für Symfony Backend (PHPUnit) und React Frontend (Jest/Vitest inkl. E2E). Deckt Unit, Functional, Integration und E2E ab – inklusive Mandantenisolation und OAuth-Flows.
|
||||||
|
license: MIT
|
||||||
|
compatibility: opencode
|
||||||
|
metadata:
|
||||||
|
audience: tester-backend-coder-frontend-coder
|
||||||
|
workflow: tdd-bdd-e2e
|
||||||
|
---
|
||||||
|
|
||||||
|
## Was ich mache
|
||||||
|
- Tests schreiben, ausführen und debuggen für das gesamte Projekt
|
||||||
|
- Test-Pyramide anwenden: Unit > Functional > Integration > E2E
|
||||||
|
- Mandantenisolation in jedem relevanten Test explizit prüfen
|
||||||
|
- OAuth-Vflows mocken und testen
|
||||||
|
- Code-Coverage messen und Lücken identifizieren
|
||||||
|
|
||||||
|
## Wann du mich nutzen solltest
|
||||||
|
- Neue Features implementiert wurden und abgedeckt werden müssen
|
||||||
|
- Tests fehlen oder veraltet sind
|
||||||
|
- Coverage-Analyse nötig ist
|
||||||
|
- CI/CD-Pipeline Tests validiert werden sollen
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### 1. Projektstruktur prüfen
|
||||||
|
```bash
|
||||||
|
pwd # aktuellen Pfad verifizieren
|
||||||
|
ls api/phpunit.xml* api/composer.json # Symfony Test-Setup prüfen
|
||||||
|
ls frontend/package.json # Frontend Test-Setup prüfen
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Bestehende Tests verstehen
|
||||||
|
- `api/tests/` durchsuchen für现有 Controller/Service-Tests
|
||||||
|
- `frontend/src/**/__tests__/` oder `frontend/src/**/*.test.{ts,tsx,js,jsx}` prüfen
|
||||||
|
- Tester-Agent-Konventionen aus `.opencode/agents/tester.md` beachten
|
||||||
|
|
||||||
|
### 3. Tests schreiben (Symfony PHPUnit)
|
||||||
|
```php
|
||||||
|
// api/tests/Unit/Entity/PersonTest.php
|
||||||
|
// api/tests/Functional/Controller/Api/VeranstaltungControllerTest.php
|
||||||
|
// api/tests/Integration/MandantIsolationTest.php
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Wichtige Konventionen:
|
||||||
|
- `WebTestCase` für Functional Tests mit `/api/*` Routen
|
||||||
|
- Mandanten-Scope in jedem Request via Header oder Session setzen
|
||||||
|
- OAuth-Token mocken (kein echter Vonova-Flow in unit tests)
|
||||||
|
- Datenbank über `test` Environment und SQLite/In-Memory oder dedizierte Test-Datenbank
|
||||||
|
|
||||||
|
### 4. Tests schreiben (Frontend)
|
||||||
|
```bash
|
||||||
|
# Jest oder Vitest – je nachdem was konfiguriert ist
|
||||||
|
npm test --prefix frontend
|
||||||
|
# bzw.
|
||||||
|
cd frontend && npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Wichtige Konventionen:
|
||||||
|
- Komponenten isoliert testen (React Testing Library bevorzugt)
|
||||||
|
- API-Calls mocken (MSW, axios-mock-adapter, etc.)
|
||||||
|
- State-Management (Redux/Zustand/etc.) separat testen
|
||||||
|
- E2E über Playwright/Cypress falls vorhanden
|
||||||
|
|
||||||
|
### 5. Mandantenisolation prüfen
|
||||||
|
Jeder Test der Daten betrifft muss validieren:
|
||||||
|
- Person A aus Mandant 1 sieht NICHT Daten von Mandant 2
|
||||||
|
- API-Filters `mandantId` korrekt scopen
|
||||||
|
- Repository-Traits/QueryBuilders filtern automatisch
|
||||||
|
|
||||||
|
### 6. Tests ausführen und Coverage prüfen
|
||||||
|
```bash
|
||||||
|
# Backend
|
||||||
|
cd api && php bin/phpunit --coverage-text --testsuite=Unit
|
||||||
|
cd api && php bin/phpunit --testsuite=functional
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
cd frontend && npm test -- --coverage
|
||||||
|
|
||||||
|
# E2E (falls konfiguriert)
|
||||||
|
cd frontend && npx playwright test
|
||||||
|
# oder
|
||||||
|
cd frontend && npx cypress run
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. DeepTrace analysieren (falls Testfehler auftreten)
|
||||||
|
Wenn Tests fehlschlagen oder unerwartetes Verhalten zeigen:
|
||||||
|
- `\\opencode\deeptrace` aufrufen um die vollständige Ausführungskette zu inspecten
|
||||||
|
- Stacktrace, Umgebungsvariablen, und abhängige Aufrufe prüfen
|
||||||
|
- Besonders nützlich bei:
|
||||||
|
- Mandantenisolation-Verletzungen (wer hat welche Daten gesehen?)
|
||||||
|
- OAuth-Token-Problemen (welcher Mock wurde nicht geladen?)
|
||||||
|
- Datenbank-State-Korruption in Integrationstests
|
||||||
|
|
||||||
|
### 8. Coverage-Ziel
|
||||||
|
- Kritische Pfade > 80%: Anwesenheitsprotokollierung, Mandantenisolation, OAuth-Flows
|
||||||
|
- Lücken dokumentieren und als TODOs erfassen
|
||||||
|
|
||||||
|
## Regeln
|
||||||
|
- Immer `pwd` vor Dateioperationen prüfen
|
||||||
|
- Test-Namen klar und deskriptiv: `testPersonCreationScopesToMandant()`
|
||||||
|
- Jeder Test testet genau eine Verhalten/Anforderung
|
||||||
|
- Arrange → Act → Assert Pattern durchhalten
|
||||||
|
- Keine echten externen Calls – alles mocken (Vonova OAuth, externe APIs)
|
||||||
|
- Test-Daten sauber aufräumen ( tearDown / fixtures )
|
||||||
@@ -32,9 +32,20 @@ Agents are defined in `.opencode/opencode.json` and `.opencode/agents/*.md`. The
|
|||||||
- `Doku/architektur.md` → Backend Architektur mit struktur & Konventionen (Provider/Processor-Pattern, Multi-Tenant Scoping)
|
- `Doku/architektur.md` → Backend Architektur mit struktur & Konventionen (Provider/Processor-Pattern, Multi-Tenant Scoping)
|
||||||
- `Doku/plan.md` → Domain-Details und Entity-Spezifikationen (Veranstaltung, Personen, Anwesenheit)
|
- `Doku/plan.md` → Domain-Details und Entity-Spezifikationen (Veranstaltung, Personen, Anwesenheit)
|
||||||
- `Doku/agents_planung.md` → 4-Phasen-Agent-Arbeitsverteilung
|
- `Doku/agents_planung.md` → 4-Phasen-Agent-Arbeitsverteilung
|
||||||
|
- `Doku/umsetzung.md` → Aktueller Projektfortschritt (immer aktuell halten!)
|
||||||
|
|
||||||
|
## Arbeitsweise
|
||||||
|
- Immer einen Subagent starten für parallele Arbeit (z.B. Backend + Frontend gleichzeitig)
|
||||||
|
- Fortschritt unter `Doku/umsetzung.md` speichern und aktualisieren
|
||||||
|
|
||||||
## What to do on first session in api/ or frontend/
|
## What to do on first session in api/ or frontend/
|
||||||
1. Read `.opencode/opencode.json` for agent definitions
|
1. Read `.opencode/opencode.json` for agent definitions
|
||||||
2. Read `Doku/architektur.md` und `Doku/plan.md` für Architektur und Domain-Anforderungen
|
2. Read `Doku/architektur.md` und `Doku/plan.md` für Architektur und Domain-Anforderungen
|
||||||
3. Read the relevant agent file from `.opencode/agents/` fur implementierung-Konventionen
|
3. Read the relevant agent file from `.opencode/agents/` fur implementierung-Konventionen
|
||||||
4. Prüfe ob Infrastruktur eingerichtet ist (docker-compose.yaml, .env.example) vor Code-Schreiben
|
4. Prüfe ob Infrastruktur eingerichtet ist (docker-compose.yaml, .env.example) vor Code-Schreiben
|
||||||
|
|
||||||
|
|
||||||
|
## Wichtige Pfad-Convention
|
||||||
|
- Alle Pfade mit `Doku/`, `.opencode/`, `api/`, `frontend/` immer relativ zum Workspaceroot
|
||||||
|
- Niemals Annahmen über Pfadnamen treffen – bei Unsicherheit zuerst `ls` oder `glob` verwenden
|
||||||
|
- Im Zweifel immer den aktuellen Pfad über das Terminal prüfen (z. B. `pwd`) bevor Dateioperationen erfolgen
|
||||||
|
|||||||
@@ -0,0 +1,291 @@
|
|||||||
|
# Symfony Entwicklungs-Dokumentation
|
||||||
|
|
||||||
|
## 1. Provider/Processor-Pattern
|
||||||
|
|
||||||
|
### Pattern-Struktur
|
||||||
|
Alle API-Anfragen durchlaufen zwei Phasen:
|
||||||
|
- **Provider**: Daten aus verschiedenen Quellen zusammenführen, Validierung vorbereiten, Domain-Logik entkoppeln
|
||||||
|
- **Processor**: Daten persistieren, Events auslösen, Response aufbauen
|
||||||
|
|
||||||
|
### Beispiel: Anwesenheit registrieren
|
||||||
|
|
||||||
|
```php
|
||||||
|
// src/Provider/AnwesenheitCreateProvider.php
|
||||||
|
final class AnwesenheitCreateProvider
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private VeranstaltungRepository $vr,
|
||||||
|
private PersonenRepository $pr,
|
||||||
|
private MandantIdScope $scope
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function provides(CreateAnwesenheitRequest $request): AnwesenheitCommand
|
||||||
|
{
|
||||||
|
$veranstaltung = $this->vr->findScop($request->veranstaltungId, $this->scope);
|
||||||
|
if (!$veranstaltung) {
|
||||||
|
throw new VeranstaltungNotFoundException($request->veranstaltungId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AnwesenheitCommand(
|
||||||
|
veranstaltung: $veranstaltung,
|
||||||
|
personenId: $request->personenId,
|
||||||
|
status: $request->status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// src/Processor/AnwesenheitCreateProcessor.php
|
||||||
|
final class AnwesenheitCreateProcessor
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private EntityManagerInterface $em,
|
||||||
|
private EventDispatcherInterface $dispatcher
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function process(AnwesenheitCommand $command): AnwesenheitCreatedEvent
|
||||||
|
{
|
||||||
|
$anwesenheit = new Anwesenheit();
|
||||||
|
$anwesenheit->setVeranstaltung($command->veranstaltung);
|
||||||
|
$anwesenheit->setPersonenId($command->personenId);
|
||||||
|
// ...
|
||||||
|
|
||||||
|
$this->em->persist($anwesenheit);
|
||||||
|
$this->em->flush();
|
||||||
|
|
||||||
|
$event = new AnwesenheitCreatedEvent($anwesenheit);
|
||||||
|
$this->dispatcher->dispatch($event);
|
||||||
|
|
||||||
|
return $event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Controller-Einbindung
|
||||||
|
```php
|
||||||
|
#[Route('/veranstaltungen/{id}/anwesenheit', name: 'erstellen_anwesenheit', methods: ['POST'])]
|
||||||
|
public function create(CreateAnwesenheitRequestDto $dto, RequestCreator $creator): JsonResponse
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$command = $this->providerProvider->provides($dto);
|
||||||
|
$result = $this->processorProvider->process($command);
|
||||||
|
return new JsonResponse(['data' => $result], 201);
|
||||||
|
} catch (EntityNotFoundException $e) {
|
||||||
|
return JsonResponse::createNotFound($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Muster-Regeln
|
||||||
|
- Provider enthalten **keine** Persistenz-Logik
|
||||||
|
- Processor enthalten **keine** Validierung-Logik
|
||||||
|
- Beide sind **stateless** und leicht testbar
|
||||||
|
- Commands und Events als Data Transfer Objekte (POPOs)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Coding Standards
|
||||||
|
|
||||||
|
### PHP Version & Basis
|
||||||
|
- PHP >= 8.4 (LTS empfohlen)
|
||||||
|
- PSR-12 als Code-Stil-Richtlinie
|
||||||
|
- PHPStan Level 6-7
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
| Typ | Konvention | Beispiel |
|
||||||
|
|-----|-----------|----------|
|
||||||
|
| Klassen | PascalCase + Substantiv | `AnwesenheitController` |
|
||||||
|
| Methoden | camelCase + Verb oder Aktonsnamen | `registriereAnwesenheit()` |
|
||||||
|
| Variablen | camelCase | `$veranstaltungsId` |
|
||||||
|
| Constants | UPPER_SNAKE_CASE | `MAX_TEILNEHMER` |
|
||||||
|
|
||||||
|
### Controller-Konventionen
|
||||||
|
- Keine Domain-Logik – immer delegieren an Provider/Processor
|
||||||
|
- DTOs für Request/Response (keine Entities direkt)
|
||||||
|
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"status": "present"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"message": "Anwesenheit erfolgreich registriert"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Exception Handling (→ siehe Abschnitt 3)
|
||||||
|
- Domain Exceptions werfen (keine raw Symfony Exceptions nach außen)
|
||||||
|
- Nur `JsonResponse` mit definiertem Error-Schema zurückgeben
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Fehlerbehandlung & API Error Schema
|
||||||
|
|
||||||
|
### Exceptions-Hierarchie
|
||||||
|
Domain Exceptions → ControllerExceptionHandler → JSON Response
|
||||||
|
|
||||||
|
```php
|
||||||
|
// Domain Exception
|
||||||
|
class VeranstaltungNotFoundException extends RuntimeException implements DomainExceptionInterface {}
|
||||||
|
|
||||||
|
// Controller Exception Handler (Kernel-Register)
|
||||||
|
#[AsController]
|
||||||
|
class ControllerExceptionHandler
|
||||||
|
{
|
||||||
|
public function __invoke(DomainExceptionInterface $e): JsonResponse
|
||||||
|
{
|
||||||
|
return new JsonResponse([
|
||||||
|
'errors' => [[
|
||||||
|
'status' => 422, // oder je nach Situation
|
||||||
|
'title' => ucfirst($e->getType()),
|
||||||
|
'detail' => $e->getMessage(),
|
||||||
|
]]
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP Status Codes
|
||||||
|
| Code | Verwendigunbg |
|
||||||
|
|------|-----------|
|
||||||
|
| `200` | OK (GET, PUT) |
|
||||||
|
| `201` | Created (POST, Entity erstellt) |
|
||||||
|
| `400` | Invalid Request Body / Validation Error |
|
||||||
|
| `403` | Forbidden (Mandant fehlt) |
|
||||||
|
| `404` | Not Found |
|
||||||
|
| `500` | Internal Server Error |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Logging & Mercure
|
||||||
|
|
||||||
|
### Events-Logging-Logik
|
||||||
|
Jeder Processor löst nach Persistierung Events aus:
|
||||||
|
```php
|
||||||
|
$this->dispatcher->dispatch(new AnwesenheitAktualisiertEvent($anwesenheit));
|
||||||
|
```
|
||||||
|
|
||||||
|
Events enthalten:
|
||||||
|
- Entity-Daten (keine sensiblen)
|
||||||
|
- Timestamp
|
||||||
|
- MandantID scope
|
||||||
|
- ActionTyp ('created', 'updated')
|
||||||
|
|
||||||
|
### Mercure Integration - Vorschläge & Nutzungsszenarien
|
||||||
|
- **Echtzeit-Anwesenheitsliste**: Websocket oder Server-Sent Events über Mercure Hub
|
||||||
|
- **Live-Benachrichtigungen** bei Statusänderungen
|
||||||
|
|
||||||
|
#### Konfigurationsoptionen für Mercure:
|
||||||
|
1. **Pulled** (Clientseitig abonnieren): Client ruft `/mercure/hub` Periodisch ab
|
||||||
|
2. **Pushed** (Serverseitig publish): Processor publiziert Events direkt an Hub
|
||||||
|
3. **Hybrid**: Pushed bei User-Aktion (z.b. Anwesenheit registrieren), Pulled bei Statusabfragen
|
||||||
|
|
||||||
|
**Empfehlung**: Mercure als optional, nur wenn Echtzeit-Funktionalität wirklich gebraucht wird. Nicht default aktivieren.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Datenbank/Migrationen - Entwicklungskonventionen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Doctrine Entity-Spezifikation
|
||||||
|
- **Entities** POPOs (Plain Old PHP Objects) mit Annotationen/Attributes für Mapping
|
||||||
|
- **Repository** nur Domain-spezifische Queries, kein raw SQL
|
||||||
|
- **Keine** Business-Logik in Entities – stattdessen Services / Provider / Processor
|
||||||
|
- **Idempotenz**: Updates per primary key
|
||||||
|
|
||||||
|
### Migrationen-Konventionen
|
||||||
|
- Jede Tabelle hat `mandant_id`, `created_at`, `updated_at` (Timestamp)
|
||||||
|
- Fremdschlüssel immer als Index + NOT NULL
|
||||||
|
|
||||||
|
|
||||||
|
- Migrations in Version kontrolliert: `php bin/console make:migration`
|
||||||
|
- **Keine** manuellen Schema-Changes ohne Migration
|
||||||
|
|
||||||
|
### Multi-Tenant-Scope Enforcement
|
||||||
|
```
|
||||||
|
Entity::mandant_id → Unique across Mandanten. Alle Queries scoped per MandantIdContext (z.B. durch Attribute/Listener)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. TDD Workflow (Red-Green-Refactor)
|
||||||
|
|
||||||
|
### Test-Schichten Priorität (TDD Red-Green)
|
||||||
|
1. **Controller/Route Tests** – Request→Response, Status-Codes, JSON Schema
|
||||||
|
2. **Provider/Processor Unittests** – isolierte logik-test der einzelnen Domäne-Layer
|
||||||
|
3. **Integrationstests** – wenn nötig (DB-Kontext, Services)
|
||||||
|
|
||||||
|
### Test-Struktur in PHPUnit
|
||||||
|
```
|
||||||
|
api/tests/Unit/Provider/
|
||||||
|
├── AnwesenheitCreateProviderTest.php ← Provider ohne DB (mock repository)
|
||||||
|
└── VeranstaltungFindProviderTest.php
|
||||||
|
|
||||||
|
api/tests/Unit/Processor/
|
||||||
|
└── AnwesenheitCreateProcessorTest.php ← Processor mit mock EM
|
||||||
|
|
||||||
|
api/tests/Functional/Controller/
|
||||||
|
└── AnwesenheitControllerTest.php ← Full HTTP request via HttpBrowser
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test-Beispiel PHPUnit
|
||||||
|
```php
|
||||||
|
// tests/Unit/Provider/AnwesenheitCreateProviderTest.php
|
||||||
|
class AnwesenheitCreateProviderTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testProvidesCommandWhenVeranstaltungFound(): void
|
||||||
|
{
|
||||||
|
$veranstaltung = new Veranstaltung();
|
||||||
|
$request = new CreateAnwesenheitRequestDto(123);
|
||||||
|
|
||||||
|
$provider = new AnwesenheitCreateProvider( // Mocks injected
|
||||||
|
VeranstaltungRepositoryMock($veranstaltung),
|
||||||
|
MandantIdScope('mandant-xyz')
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = $provider->provides($request);
|
||||||
|
|
||||||
|
self::assertInstanceOf(AnwesenheitCommand::class, $result);
|
||||||
|
self::assertSame($veranstaltung, $result->getVeranstaltung());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test-Prioritäten für Implementierung
|
||||||
|
1. Controller/Routen-Tests schreiben → **failend** (RED)
|
||||||
|
2. Minimal-Implementierung schreiben → **test bestanden** (GREEN)
|
||||||
|
3. Refactor (Code-Qualität, Tests verbessern)
|
||||||
|
4. Nächster Test (höhere Abdeckung im Provider/Processor)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Framework-Bundles
|
||||||
|
|
||||||
|
### Philosophie
|
||||||
|
- Kern-Symfony nur verwenden (Mime, HttpFoundation, Serializer, Validator, Security)
|
||||||
|
- Neue Bundles **nur bei Bedarf** dokumentieren und begründen
|
||||||
|
|
||||||
|
|
||||||
|
| Bundle | Verwendung | Begründung erforderlich |
|
||||||
|
|--------|------------|------------------------|
|
||||||
|
| `symfony/maker` | Boilerplate | Nur für Initialisierung, nicht produktiv |
|
||||||
|
| `api-platform/core` | REST API | **Explizit vermieden** – manuelle Controller |
|
||||||
|
| `sensio/framework-extra-bundle` | Annotations/Cache | Symfony 7.4 native statt Bundles bevorzugen |
|
||||||
|
| `symfonycasts/validator` | Custom Validators | Nur bei komplexer Validierung |
|
||||||
|
| `mercure/bundle` | Mercure-Integration | Nur wenn Echtzeit benötigt wird |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Zusammenfassung Entwicklungsflow
|
||||||
|
1. Test schreiben (RED) → failend
|
||||||
|
2. Minimal-Implementierung als Provider/Processor/Gateway
|
||||||
|
3. Test bestehen lassen (GREEN)
|
||||||
|
4. Refaktorieren und Qualität prüfen (PHPStan, Coding Standards)
|
||||||
|
5. Entity/Migration erstellen wenn nötig **nach** Code-Phase
|
||||||
|
|
||||||
|
Die Doku wird mit dem Projekt aktualisiert.
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# Umsetzung – Vollversammlung
|
||||||
|
|
||||||
|
## Aktueller Stand (28. Juni 2026)
|
||||||
|
|
||||||
|
### Erledigt ✅
|
||||||
|
- **Infrastruktur**: docker-compose.yaml mit PostgreSQL, Nginx, Mercure, Mailpit, Vite
|
||||||
|
- **Dockerfiles**: api/Dockerfile.dev, api/Dockerfile.prod, frontend/Dockerfile.dev
|
||||||
|
- **.env Dateien**: api/.env.example, frontend/.env.example
|
||||||
|
- **docker-entrypoint.sh** für Symfony Setup
|
||||||
|
|
||||||
|
### Offene Aufgaben (priorisiert)
|
||||||
|
1. Symfony Boilerplate erstellen (Entities: Veranstaltung, Person, Anwesenheit)
|
||||||
|
2. React Boilerplate erstellen (Router, State-Management)
|
||||||
|
3. CRUD-API-Endpoints entwickeln
|
||||||
|
4. Frontend-Seiten aufbauen (Veranstaltung, Personen, Anwesenheit)
|
||||||
|
5. Statistikseite implementieren (Anwesenheitszahlen, Anwesenheitsquote, Geschlechterquote)
|
||||||
|
6. OAuth-Integration (Vonova)
|
||||||
|
7. Tests schreiben (Unit, Functional, E2E)
|
||||||
|
8. Security-Review durchführen
|
||||||
|
|
||||||
|
### Nächste Schritte
|
||||||
|
- Symfony Boilerplate start
|
||||||
Reference in New Issue
Block a user