Files
vollversammlung/Doku/architektur.md
T

69 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Backend-Architektur Veranstaltungs-Tool (Konzept)
## Ziel
Mandantenfähiges Backend mit 3 Schichten pro fachlicher Domäne und mehreren Clients/Entry-Points.
## Struktur
```
api/
├── public/index.php ← Entrypoint
└── src/
├── UI/{ClientName}/{FeatureName}/ ← pro Client + Use-Case (PascalCase, deutsch)
│ ├── Controller/ REST-Endpunkte (/api/*), Commands etc.
│ ├── Request/ Request-DTOs
│ └── Response/ Response-DTOs
├── Logic/{FeatureName}/ ← Business Rules pro Use-Case
│ ├── Manager/ Cache, Workflow, Aggregate
│ ├── Calculator/ Berechnungen (Statistiken)
│ ├── Model/ Feature-Modelle
│ ├── Provider/*ProviderInterface Interfaces für Data-Layer
│ ├── Processor/*ProcessorInterface Interface für Verarbeitungslogik
│ └── Shared/ Feature-spezifisches Shared (wenn notwendig)
├── Data/{FeatureName}/ ← Domain-Objects, DB-Zugriff pro Use-Case
│ ├── Entity/ Doctrine Entities
│ └── Repository/ Repo-Interfaces + Implementierungen
└── Shared/ ← Nur wirklich entitätsübergreifende Basics
├── BaseEntity.php
└── UuidGenerator.php
```
## Client-Namenskonvention
- `API` → REST-Schnittstelle (UI/API/*)
- `Console` → Symfony Commands (UI/Console/*)
## Feature-Namenskonvention
Use-Case-basiert, PascalCode auf Deutsch. ZB:
- `Personen` (nicht Personenliste / PersonController)
- `Veranstaltungen` (nicht VeranstaltungenIndex)
- `Anwesenheit` (nicht AnwesenheitsstatusErfassung)
Beispiel-Pfad: `UI/API/Personen/Controller/PersonenController.php`
**Model/** pro Feature Ordner mit ggf. mehreren Models definiert die Feature-Grenze.
## Entry-Points
Mehrere Clients via Router-basierte Routing:
- `/api/*` → REST-Controller (`UI/API/{Feature}/Controller/`)
- Console → Symfony Commands (`UI/Console/{Feature}/Command/`)
- Messages → Messenger Handler
## Entscheidungen
### Provider und Processoren
**Provider** implementieren die `*ProviderInterface`. Sie rufen Daten ab per Doctrine Repositories/Entities oder über API-Aufrufe. Das Mapping zwischen Entities und Model-Objekten erfolgt in separaten **Mapper**-Klassen, die in **Data/** liegen. Provider binden so die Data-Schicht an die Logic-Schicht.
**Processoren** funktionieren analog für schreibende Prozesse (`*ProcessorInterface`).
### Shared-Klassen
Echt entitätsbergreifende Basis-Klassen (`BaseEntity`, `UuidGenerator`) leben in `src/Shared/`. Feature-spezifisches Shared liegt innerhalb des Features, zB:
```
src/Logic/Veranstaltungsmanagement/Shared/JsonSerializer.php
```
### Multi-Tenant Scoping
Alle Repository-Queries werden per **Doctrine SQL Builder Trait** mit `mandant_id` gefiltert. Der Scope wird automatisch angehängt sowohl lesend als auch schreibend. Tenantübergreifende Operationen sind technisch nicht möglich, da alle Repos implicit scopen. Das schützt vor unbeabsichtigten Mandanten-Überschneidungen. Bei Bedarf kann eine explizite WithoutScope-Schicht eingeführt werden.
### Dependency Injection
Nur explizit über `services.yaml`, wenn notwendig. Standardmäßig wird Auto-Wiring mit Konventionen verwendet (`*ProviderInterface`, `*ProcessorInterface`).