Files
votianng/README.md
T
Sven 75e2bf2bec Binde Auftragshistorie an und korrigiere Kundenanzeige
Ergänzt die lesende Historien-API mit Verlaufsanzeige und ordnet Auftragskunden dem effektiven Zahler zu. Enthält VS-Code-Debugkonfiguration, Dokumentation und Regressionstests.

Validiert mit Frontend-Build, 76 Backend-Tests und 25 Browsertests. Live-Datenbankprüfung wegen fehlender Erreichbarkeit offen.
2026-10-07 20:40:58 +02:00

132 lines
11 KiB
Markdown

# VoTiAn NG · Stadtbote
React-/TypeScript-Oberfläche und Spring-Boot-Anbindung für die vorhandene PHP-Anwendung in `votian/`. Die neue Anwendung verwendet **dieselbe vorhandene MySQL-Datenbank und deren Tabellen**. Sie enthält keine eigene Datenbank, keine automatischen Schemaänderungen und keine Demodatensätze.
## Stand
Die Altanwendung wurde fachlich und technisch analysiert. Die neue Oberfläche bildet Auftragslisten, Disposition, Touren, Kunden, Kuriere und Auswertung ab. Das Spring-Boot-Backend greift ausschließlich über den zentralen `DatabaseService` auf das vorhandene Schema zu. Die Anmeldung verwendet vorhandene VoTiAn-Zentralenbenutzer mit ihren Niederlassungs- und Mitarbeiterrechten.
**Die vollständige Ablösung der PHP-Anwendung ist noch nicht abgeschlossen.** Schreibende Vorgänge wie Auftragserfassung, Tarifberechnung, Storno und Rechnungserzeugung haben im Altcode zahlreiche weitere Auswirkungen (unter anderem Fahrerbenachrichtigungen und Gegenbuchungen). Solange diese nicht vollständig portiert und am aktiven Bestand geprüft sind, öffnet die Oberfläche dafür die passenden Module der vorhandenen PHP-Anwendung, wenn `LEGACY_APP_URL` konfiguriert ist. Es gibt keine vereinfachten Schreibzugriffe, die diese Regeln umgehen.
Die vollständige Analyse und Abdeckungsmatrix stehen in [docs/ALTSYSTEM-ANALYSE.md](docs/ALTSYSTEM-ANALYSE.md).
## Start
Benötigt: Java 21, Node.js 22.12 oder neuer, Python 3 sowie der Netzwerk-/VPN-Zugang zur bestehenden Datenbank. Maven wird über den mitgelieferten Wrapper verwendet.
```bash
cd /Users/svencarstensen/Documents/Entwicklung/Source/Kunden/Assecutor/votianNG
./dev.sh
```
Die Oberfläche ist anschließend unter `http://localhost:5173` erreichbar. `Strg+C` beendet die gestarteten Prozesse. Das Backend-Protokoll liegt in `work/backend.log`.
`dev.sh`, `run.sh` und die Datenbankdiagnose laden `DB_URL`, `DB_USER` und `DB_PASSWORD` aus der lokalen `.env` im Projektstamm. Bereits gesetzte Umgebungsvariablen haben Vorrang. Die Zugangsdaten werden ausschließlich als Prozessumgebung an Java übergeben, ohne sie auszugeben oder in Prozessargumente zu schreiben.
Die vorhandenen lokalen Datenbankwerte wurden nach `.env` übernommen. Bei einer neuen Einrichtung `.env.example` nach `.env` kopieren und die drei Werte eintragen. `DB_URL` enthält den vom jeweiligen Rechner erreichbaren Host bzw. die VPN-Adresse, Port und Datenbanknamen:
```bash
DB_URL=jdbc:mariadb://DB-HOST:3306/DB-NAME?connectTimeout=3000&socketTimeout=5000&allowMultiQueries=false
```
Diese Zeile gehört in `.env`. Werte werden wörtlich gelesen; `$`, `#`, `=` und Backslashes im Passwort bleiben erhalten. Die Datei wird nicht als Shellskript ausgeführt und sollte nicht mit `source` geladen werden. Für die zusätzliche Verwendung mit Docker die Werte ohne umschließende Anführungszeichen schreiben. `.env` und lokale Varianten sind per `.gitignore` ausgeschlossen; `.env.example` enthält ausschließlich Platzhalter.
Nur die Konfiguration ohne Datenbankverbindung prüfen:
```bash
python3 scripts/run-backend.py --check-config
```
Die neue Anwendung liest `connection.local.json` und die PHP-Konfiguration nicht mehr als Zugangsdatenquelle. Der PHP-Altbestand bleibt eigenständig; seine Konfiguration wird durch diese Umstellung nicht verändert.
## Debuggen in VS Code
Den Projektstamm `votianNG` in VS Code öffnen. Benötigt werden das **Extension Pack for Java**, Java 21 und Google Chrome. Die Frontend-Abhängigkeiten einmalig mit `npm ci --prefix frontend` installieren und die lokale `.env` wie oben beschrieben einrichten.
Unter **Ausführen und Debuggen** die Konfiguration **VoTiAn NG: Backend + Frontend** auswählen und mit `F5` starten. Das Backend wird vom Java-Debugger gebaut und mit der `.env` auf `127.0.0.1:8080` gestartet. Vite läuft auf `127.0.0.1:5173` und öffnet automatisch Chrome mit aktiviertem Browser-Debugger. Haltepunkte sind sowohl in Java als auch in React/TypeScript möglich. Die beiden Komponenten lassen sich über die Einzelkonfigurationen auch separat starten.
Die Ports sind im Debugstart festgelegt, passend zum Vite-API-Proxy. Ein bereits laufendes `dev.sh` vorher beenden. Beim Stoppen einer Komponente des gemeinsamen Starts werden beide Server und die zugehörige Browser-Debugsitzung beendet.
Der Java-Debugger liest `.env` mit dem üblichen dotenv-Parser: `$` bleibt wörtlich, ein unquotiertes `#` beginnt dagegen einen Kommentar. Bei solchen Werten sind Anführungszeichen erforderlich; für Docker gegebenenfalls eine separate Datei mit unquotierten Werten verwenden.
## Gebündelte Anwendung
```bash
./build.sh
./run.sh
```
`build.sh` baut React, integriert die gebauten Dateien in das Spring-Boot-JAR und führt die Backend-Tests aus. Die gebündelte Oberfläche ist über `http://localhost:8080` erreichbar. `run.sh` übernimmt dieselbe `.env` wie der Entwicklungsstart. Build und Unit-Tests laden keine lokalen Datenbankzugangsdaten.
## Docker-Image veröffentlichen
```bash
docker login registry.assecutor.org
./docker_push.sh
# Alternativer Image-Tag:
./docker_push.sh 0.1
```
Das Skript führt `build.sh` einschließlich Tests aus und pusht das Java-21-Image mit gebündeltem React-Frontend für `linux/amd64` nach `registry.assecutor.org/votianng`. Ohne Argument verwendet es die Version aus `backend/pom.xml`; ein expliziter Tag ändert nur den Image-Tag. Das Ziel lässt sich über `REGISTRY_IMAGE` überschreiben.
Im Container lauscht die Anwendung auf Port 8080 an `0.0.0.0`. Die `.env` wird beim Containerstart übergeben:
```bash
docker run --rm --env-file .env -p 127.0.0.1:8080:8080 registry.assecutor.org/votianng:0.1
```
Die vorhandene PHP-Anwendung und `.env` sind nicht im Image enthalten. Bei Bedarf `LEGACY_APP_URL` zusätzlich als Umgebungsvariable übergeben. Beim direkten Start über Maven oder `java -jar` wird `.env` über den gemeinsamen Wrapper geladen, beispielsweise aus `backend/`: `python3 ../scripts/env_config.py ./mvnw spring-boot:run`.
## Anmeldung und Reverse Proxy
VoTiAn verwendet serverseitige Sitzungen mit dem Cookie `VOTIANSESSION`. Die Systemzugangsdaten werden einmal beim Anmelden übertragen; die Oberfläche speichert sie nicht im Browser und setzt keinen `Authorization`-Header. Ein zusätzlicher HTTP-Basic-Passwortschutz im Nginx Proxy Manager kann deshalb bestehen bleiben: Dessen Zugangsdaten verwaltet der Browser unabhängig von der VoTiAn-Sitzung. Die Abmeldung in VoTiAn beendet nur die Sitzung der Anwendung.
Für `https://votian.app` muss der Proxy die Oberfläche und `/api/**` an denselben VoTiAn-Dienst weiterleiten, Cookies durchlassen und das ursprüngliche HTTPS-Protokoll als `X-Forwarded-Proto: https` übermitteln. Die Anwendung wertet diese Header mit der nativen Tomcat-Unterstützung aus. Nur der vertrauenswürdige Proxy sollte den Backend-Port erreichen; er muss vom Client übermittelte Forwarded-Header ersetzen. Tomcat vertraut standardmäßig internen Proxyadressen. Bei anderer Netzwerkstruktur die erlaubten Proxyadressen gezielt über `SERVER_TOMCAT_REMOTEIP_INTERNAL_PROXIES` konfigurieren; die Prüfung nicht durch einen leeren Wert abschalten. Siehe [Spring Boot: Reverse Proxy](https://docs.spring.io/spring-boot/3.5/how-to/webserver.html#howto.webserver.use-behind-a-proxy-server).
Im HTTPS-Produktionsbetrieb zusätzlich `SERVER_SERVLET_SESSION_COOKIE_SECURE=true` als Container-Umgebungsvariable setzen, zum Beispiel mit `docker run --env-file .env -e SERVER_SERVLET_SESSION_COOKIE_SECURE=true ...`. Damit wird das Sitzungscookie ausschließlich über HTTPS übertragen. Der direkte HTTP-Aufruf per Server-IP ist dann kein Anmeldeweg mehr. Für die lokale Entwicklung über HTTP diese Einstellung weglassen; ohne explizite Vorgabe richtet sich `Secure` nach dem vom Backend erkannten Request-Protokoll.
Das Sitzungscookie ist `HttpOnly` und `SameSite=Lax`. Standardmäßig ist nach 30 Minuten ohne Anfrage an die Sitzung eine erneute Anmeldung erforderlich. Sitzungen liegen im Arbeitsspeicher des Backends und gehen bei einem Neustart verloren; mehrere Instanzen benötigen Sitzungsaffinität oder eine später einzurichtende gemeinsame Sitzungsablage. Benutzerrechte werden bei der Anmeldung geladen und gelten bis zur Abmeldung bzw. zum Sitzungsablauf. Änderungen an Konten oder Rechten beenden vorhandene Sitzungen nicht sofort.
## Konfiguration
| Variable | Bedeutung |
|---|---|
| `DB_URL`, `DB_USER`, `DB_PASSWORD` | Datenbankzugang aus `.env`; Prozessumgebung hat Vorrang |
| `LEGACY_APP_URL` | Basis-URL der vorhandenen PHP-Anwendung, damit Aktionen die bestehenden Fachabläufe öffnen |
| `PORT` | Spring-Boot-Port, Standard 8080 |
| `SERVER_ADDRESS` | Bind-Adresse, Standard `127.0.0.1` |
| `FORWARD_HEADERS_STRATEGY` | Auswertung der Proxy-Header, Standard `native` |
| `SERVER_SERVLET_SESSION_COOKIE_SECURE` | Im HTTPS-Produktionsbetrieb `true` setzen; lokal über HTTP weglassen |
| `SESSION_TIMEOUT` | Ablauf bei Inaktivität, Standard `30m` |
| `MAX_RESULTS` | Obergrenze des geladenen Listenausschnitts, Standard 500 |
Die neue Anwendung ist standardmäßig nur lokal erreichbar. Für einen Serverbetrieb sind TLS und die korrekte Weiterleitung über einen Reverse Proxy zu konfigurieren. Es werden keine Standardkonten angelegt. Kunden- und Kurierlogins sind noch keine portierten Zugangswege; vorhandene Zentralenrechte werden nicht pauschal erweitert.
## Prüfungen
```bash
python3 -m unittest discover -s tests -p 'test_*.py' -v
cd backend && ./mvnw test
```
Die Tests verwenden Mocks und getrennte Testfixtures im Arbeitsspeicher der Tests. Sie erzeugen keine Testdatenbank und führen keine Schreibzugriffe gegen den Bestand aus. Ein erfolgreicher Build ersetzt nicht die noch notwendige Prüfung mit aktivem VPN, dem korrekten Datenbankendpunkt und fachlichen Vergleichsfällen aus dem Altbetrieb.
Die optionale Diagnose `python3 scripts/check-database.py` startet das gebaute Backend-JAR im Modus `--database-check`, ohne Webserver. Verbindung und benötigte Tabellenspalten werden ausschließlich über denselben `DatabaseService` mit `SELECT` auf Serverversion und `information_schema` geprüft. Die Diagnose liest keine Auftrags-/Benutzerdatensätze, gibt keine Zugangsdaten aus und beendet danach den Prozess. Ein eigener Python-Datenbanktreiber ist nicht mehr erforderlich.
## Datenbank-Serviceschicht
Alle Zugriffe der neuen Anwendung laufen über `backend/src/main/java/de/stadtbote/votian/database/DatabaseService.java`: Anmeldung, Aufträge und Stationen, Kunden, Kuriere, CSV-Daten sowie Verbindungs- und Schemadiagnose. Nur dieser Service verwendet JDBC und steuert Datenbanktransaktionen. Auftragsanzahl, Liste und Stationen werden in einer gemeinsamen Lesetransaktion gelesen. SQL-Werte werden als Parameter gebunden.
Der zentrale Schreibzugang `update(...)` ist in der aktuellen Ausbaustufe gesperrt und öffnet keine Verbindung. Die Fachprozesse für schreibende Vorgänge sind weiterhin erst vollständig zu portieren. Architekturtests prüfen Java-Bytecode und Python-Launcher auf Direktzugriffe außerhalb dieser Schicht. Die vorhandene PHP-Anwendung ist von dieser Umstellung nicht betroffen.
## Projektstruktur
```text
votian/ Bestehende PHP-Anwendung, unverändert weiter nutzbar
frontend/ React, TypeScript, Vite und Stadtbote-Oberfläche
backend/ Spring Boot, JDBC und vorhandene Benutzer-/Rechtestruktur
docs/ Analyse, Fachregeln, Abdeckung und weitere Abnahme
scripts/ Lokaler Start mit vorhandener Konfiguration
tests/ Zusätzliche Konfigurations- und Browserprüfungen
```