Toter Code im Backend (Prüfung 03.10.2026) #45

Open
opened 2026-10-03 18:14:30 +00:00 by claude · 2 comments
Collaborator

Befund einer Prüfung des gesamten Backends auf toten Code (03.10.2026, Stand main bei 8237f245).

Methode: Skript über alle 343 Produktiv- und 221 Testdateien, das Typen, Methoden, Felder, Enum-Konstanten, Record-Komponenten, REST-Endpunkte und Config-Schlüssel gegen Backend, Tests, die drei Frontends, E2E, Skripte und Doku abgleicht. Dazu PMD mit den Unused-Regeln (main + test) und mvn dependency:analyze. Jeder Kandidat ist per grep und Git-Historie gegengeprüft.

1. Sicher tot im Produktivcode

Was Wo Herkunft
Record TeamRequest samt innerem TeamPlayerRequest competition/api/TeamRequest.java kein Aufrufer, kein Test, nicht im OpenAPI-Schema; verwaist seit a40ac04e (nie aufgerufenen Meldungs-Pfad entfernt)
OfficialRepository.findByClubIdAndFunction competition/repository/OfficialRepository.java:17 kein Aufrufer, kein Test; letzter Nutzer fiel mit den Amtszeiten (610bd88c, a80588c1)
VenueRepository.findByClubIdAndName competition/repository/VenueRepository.java:18 kein Aufrufer, kein Test; fiel mit ce0e0260 (Spiellokale fortschreiben statt löschen)
UserClubMappingRepository.deleteByClubId shared/repository/UserClubMappingRepository.java:18 kein Aufrufer, auch nicht aus Tests; übrig aus d9d3e1c7 (DB-Kaskaden statt Java-Schleifen)
Endpunkt GET /api/seasons/latest (getLatestSeason) competition/resource/SeasonResource.java:116 kein Frontend, kein Skript, keine E2E, keine Doku ruft ihn auf; nur der eigene Test in SeasonResourceTest
@Inject SeasonRepository seasonRepository competition/service/CsvImportService.java:35 und competition/service/LigaViewService.java:36 injiziert, nie benutzt
lokale Variable hasPhone competition/service/PdfService.java:235 gesetzt, nie gelesen (PMD UnusedLocalVariable)
ScrapingResultResponse.clubsImported competition/api/ScrapingResultResponse.java kein Konsument; das Portal zeigt nur message, playersImported, skipped
Roles.CAPTAIN shared/Roles.java:14 nie referenziert. Die Klasse nennt sich „die einzige Quelle für Zugriffsprüfungen“, aber alle elf @RolesAllowed verwenden Literale. Kein toter Code im engen Sinn, aber ein Widerspruch zur eigenen Doku

2. Produktivcode, den nur Tests aufrufen

Entscheidung je Methode nötig: bewusst vorgehaltener Baustein, oder mit dem Aufrufer gestorben und vom Test künstlich am Leben gehalten.

Methode Hinweis
PlayerRepository.findByNameAndClubId letzter Produktiv-Aufrufer fiel mit b077f557 (Verein als Stichtagsfrage)
PlayerRepository.findByLicenseNumberAndClubId 13 Testaufrufe plus DummyImportService, kein Produktiv-Aufrufer
EloSnapshotRepository.findByPlayerAndSeason Aufrufer fiel mit 81ebe896 (Verlauf über alle Halbrunden)
EloSnapshotRepository.findBySeasonOrdered Aufrufer fiel mit 5781bdcb (Spielerverzeichnis zeigt ganze Laufbahn)
JwtService.isAdmin Aufrufer fiel mit fdb3e5b2 (Export/Import aus DatabaseResource entfernt)
EloService.isCutoffReached Javadoc nennt den strukturellen Stichtag nach WR 1.4.5.2; in der Produktion fragt ihn niemand ab
Validity.isOpen nur Tests
ArticleRepository.latestNews nur Tests
TtvpCupBracket.participantsAt nur TtvpCupBracketTest
deleteByClubId in GameDayEntryRepository, VenueRepository, RegistrationRepository einziger Aufrufer ist das Aufräumen in CsvImportServiceTest

3. Toter Testcode

  • TestSeasonNames (src/test/java/ch/sffs/tt/TestSeasonNames.java), die ganze Klasse: kein Test referenziert sie, trotz ausführlichem Javadoc
  • CupTestFixtures.staerksteMannschaft (Zeile 194): kein Aufrufer
  • FixtureImportTestFixtures: die @Inject-Felder categoryRoundRepository (Zeile 49) und matchWeekRepository (Zeile 51) werden nie benutzt

Geprüft und nicht tot

  • alle Resource-Klassen (Einstiegspunkte), CaptainReminderService (@Scheduled), CompetitionClubDirectory (CDI über das Interface ClubDirectory), UploadSeedService und TestDataInitializer (@Observes StartupEvent), ProblemDetailsMapper (@Provider)
  • die Felder der Import-Antworten (FixtureImportResponse, TournamentImportResponse, SeasonSeedResponse, EloReportResponse): kein Frontend liest sie, aber die Skripte drucken die komplette JSON-Antwort, also sind sie sichtbar
  • alle Request-Felder werden serverseitig gelesen; alle Enum-Konstanten sind Datenwerte in DB oder Frontend
  • keine ungenutzten privaten Methoden oder Felder, keine ungenutzten Methodenparameter, keine ungenutzten Maven-Abhängigkeiten, keine Tabelle ohne Entity; Spotless räumt Importe schon weg

Nebenbefunde von PMD (kein toter Code)

  • überflüssige Klammern: TournamentResource.java:458 (zweimal), EloCutoffService.java:165
  • vereinfachbarer Ternär: ArticleResource.java:178
  • leerer Catch in SeasonSeedService.java:287 ist kommentiert und gewollt

Vorschlag

Abschnitt 1 und 3 in einem Commit entfernen. Abschnitt 2 braucht je Methode eine Entscheidung von Olli.

Befund einer Prüfung des gesamten Backends auf toten Code (03.10.2026, Stand `main` bei `8237f245`). **Methode:** Skript über alle 343 Produktiv- und 221 Testdateien, das Typen, Methoden, Felder, Enum-Konstanten, Record-Komponenten, REST-Endpunkte und Config-Schlüssel gegen Backend, Tests, die drei Frontends, E2E, Skripte und Doku abgleicht. Dazu PMD mit den Unused-Regeln (main + test) und `mvn dependency:analyze`. Jeder Kandidat ist per grep und Git-Historie gegengeprüft. ## 1. Sicher tot im Produktivcode | Was | Wo | Herkunft | |---|---|---| | Record `TeamRequest` samt innerem `TeamPlayerRequest` | `competition/api/TeamRequest.java` | kein Aufrufer, kein Test, nicht im OpenAPI-Schema; verwaist seit `a40ac04e` (nie aufgerufenen Meldungs-Pfad entfernt) | | `OfficialRepository.findByClubIdAndFunction` | `competition/repository/OfficialRepository.java:17` | kein Aufrufer, kein Test; letzter Nutzer fiel mit den Amtszeiten (`610bd88c`, `a80588c1`) | | `VenueRepository.findByClubIdAndName` | `competition/repository/VenueRepository.java:18` | kein Aufrufer, kein Test; fiel mit `ce0e0260` (Spiellokale fortschreiben statt löschen) | | `UserClubMappingRepository.deleteByClubId` | `shared/repository/UserClubMappingRepository.java:18` | kein Aufrufer, auch nicht aus Tests; übrig aus `d9d3e1c7` (DB-Kaskaden statt Java-Schleifen) | | Endpunkt `GET /api/seasons/latest` (`getLatestSeason`) | `competition/resource/SeasonResource.java:116` | kein Frontend, kein Skript, keine E2E, keine Doku ruft ihn auf; nur der eigene Test in `SeasonResourceTest` | | `@Inject SeasonRepository seasonRepository` | `competition/service/CsvImportService.java:35` und `competition/service/LigaViewService.java:36` | injiziert, nie benutzt | | lokale Variable `hasPhone` | `competition/service/PdfService.java:235` | gesetzt, nie gelesen (PMD UnusedLocalVariable) | | `ScrapingResultResponse.clubsImported` | `competition/api/ScrapingResultResponse.java` | kein Konsument; das Portal zeigt nur `message`, `playersImported`, `skipped` | | `Roles.CAPTAIN` | `shared/Roles.java:14` | nie referenziert. Die Klasse nennt sich „die einzige Quelle für Zugriffsprüfungen“, aber alle elf `@RolesAllowed` verwenden Literale. Kein toter Code im engen Sinn, aber ein Widerspruch zur eigenen Doku | ## 2. Produktivcode, den nur Tests aufrufen Entscheidung je Methode nötig: bewusst vorgehaltener Baustein, oder mit dem Aufrufer gestorben und vom Test künstlich am Leben gehalten. | Methode | Hinweis | |---|---| | `PlayerRepository.findByNameAndClubId` | letzter Produktiv-Aufrufer fiel mit `b077f557` (Verein als Stichtagsfrage) | | `PlayerRepository.findByLicenseNumberAndClubId` | 13 Testaufrufe plus `DummyImportService`, kein Produktiv-Aufrufer | | `EloSnapshotRepository.findByPlayerAndSeason` | Aufrufer fiel mit `81ebe896` (Verlauf über alle Halbrunden) | | `EloSnapshotRepository.findBySeasonOrdered` | Aufrufer fiel mit `5781bdcb` (Spielerverzeichnis zeigt ganze Laufbahn) | | `JwtService.isAdmin` | Aufrufer fiel mit `fdb3e5b2` (Export/Import aus `DatabaseResource` entfernt) | | `EloService.isCutoffReached` | Javadoc nennt den strukturellen Stichtag nach WR 1.4.5.2; in der Produktion fragt ihn niemand ab | | `Validity.isOpen` | nur Tests | | `ArticleRepository.latestNews` | nur Tests | | `TtvpCupBracket.participantsAt` | nur `TtvpCupBracketTest` | | `deleteByClubId` in `GameDayEntryRepository`, `VenueRepository`, `RegistrationRepository` | einziger Aufrufer ist das Aufräumen in `CsvImportServiceTest` | ## 3. Toter Testcode - `TestSeasonNames` (`src/test/java/ch/sffs/tt/TestSeasonNames.java`), die ganze Klasse: kein Test referenziert sie, trotz ausführlichem Javadoc - `CupTestFixtures.staerksteMannschaft` (Zeile 194): kein Aufrufer - `FixtureImportTestFixtures`: die `@Inject`-Felder `categoryRoundRepository` (Zeile 49) und `matchWeekRepository` (Zeile 51) werden nie benutzt ## Geprüft und nicht tot - alle Resource-Klassen (Einstiegspunkte), `CaptainReminderService` (`@Scheduled`), `CompetitionClubDirectory` (CDI über das Interface `ClubDirectory`), `UploadSeedService` und `TestDataInitializer` (`@Observes StartupEvent`), `ProblemDetailsMapper` (`@Provider`) - die Felder der Import-Antworten (`FixtureImportResponse`, `TournamentImportResponse`, `SeasonSeedResponse`, `EloReportResponse`): kein Frontend liest sie, aber die Skripte drucken die komplette JSON-Antwort, also sind sie sichtbar - alle Request-Felder werden serverseitig gelesen; alle Enum-Konstanten sind Datenwerte in DB oder Frontend - keine ungenutzten privaten Methoden oder Felder, keine ungenutzten Methodenparameter, keine ungenutzten Maven-Abhängigkeiten, keine Tabelle ohne Entity; Spotless räumt Importe schon weg ## Nebenbefunde von PMD (kein toter Code) - überflüssige Klammern: `TournamentResource.java:458` (zweimal), `EloCutoffService.java:165` - vereinfachbarer Ternär: `ArticleResource.java:178` - leerer Catch in `SeasonSeedService.java:287` ist kommentiert und gewollt ## Vorschlag Abschnitt 1 und 3 in einem Commit entfernen. Abschnitt 2 braucht je Methode eine Entscheidung von Olli.
Author
Collaborator

Abgleich mit dem Projekt-Review vom 11.10.2026 (docs/reviews/2026-10-11-project-review.json, Commit 834d38b, liegt auf feature/phasen-kopfzeile). Der Lauf war ein Kalibrierungslauf, seine Befunde sind trotzdem einzeln geprüft. 16 der 21 Produktivcode-Punkte dieses Issues stehen dort als eigene Befunde (quality/2, alle Low). Wer dieses Issue umsetzt, behebt sie mit.

Abschnitt 1 — sicher tot

Punkt Review-Befund
TeamRequest samt TeamPlayerRequest — (nicht im Bericht, siehe unten)
OfficialRepository.findByClubIdAndFunction QUAL-a99bdc
VenueRepository.findByClubIdAndName QUAL-fd4cbf
UserClubMappingRepository.deleteByClubId QUAL-cb7f0b
GET /api/seasons/latest (getLatestSeason) QUAL-4d6fb5
seasonRepository in CsvImportService QUAL-d5a5e9
seasonRepository in LigaViewService QUAL-fefdac
lokale Variable hasPhone (PdfService) — (nicht im Bericht)
ScrapingResultResponse.clubsImported — (nicht im Bericht)
Roles.CAPTAIN nicht mehr tot — seit b58cdb19 (10.10.) dreimal in LoginTaskService benutzt. Der Widerspruch zur eigenen Doku bleibt: 80 von 83 @RolesAllowed in main verwenden weiter Literale, nur drei Roles.*

Abschnitt 2 — nur Tests rufen auf

Punkt Review-Befund
PlayerRepository.findByNameAndClubId QUAL-ea299e
PlayerRepository.findByLicenseNumberAndClubId QUAL-8dc20d
EloSnapshotRepository.findByPlayerAndSeason QUAL-65191d
EloSnapshotRepository.findBySeasonOrdered QUAL-80580f
JwtService.isAdmin QUAL-ce676c
EloService.isCutoffReached QUAL-2b8d13
ArticleRepository.latestNews QUAL-b415e2
GameDayEntryRepository.deleteByClubId QUAL-ba2dc1
VenueRepository.deleteByClubId QUAL-c04082
RegistrationRepository.deleteByClubId QUAL-54818a
Validity.isOpen — (im Lauf übersehen; der seither gebaute Sweep der Rubrik v12 findet ihn)
TtvpCupBracket.participantsAt — (ebenso)

Abschnitt 3 — toter Testcode

Nicht im Bericht: die Rubrik misst nur Produktivcode. Am heutigen Stand (d8d816c) weiter vorhanden: TestSeasonNames, CupTestFixtures.staerksteMannschaft.

Was das Review nicht sieht

TeamRequest (ein ganzer Typ), hasPhone (lokale Variable) und clubsImported (Record-Komponente) erfasst auch der neue Sweep nicht — er prüft Methoden, injizierte Felder und Endpunkte. Eingetragen im Rubrik-Backlog des Skills. Für dieses Issue ändert das nichts: die Punkte bleiben hier stehen.

Im Review zusätzlich, nicht in diesem Issue

Backend-Code, der zum Teil erst nach dem 03.10. entstanden ist: TeamPlayerRepository.findOpenByTeamAndPlayer (QUAL-2ca5ea), EloResource.baselineRepository (QUAL-470157), GET /api/seasons/active/name (QUAL-ac1995), HalbseriePublicationService.isPublished (QUAL-55ed96), SeasonHalbserieService.halbserieOf (QUAL-544503), SeasonSetupService.ensureCategories (QUAL-9d9752). QUAL-0bdacc (GameDayEntryRepository.findAllValidAt) ist ein Fehlalarm: der Aufrufer steht in PublicClubResource, die wegen eines rohen NUL-Bytes im Quelltext für grep unsichtbar ist.

Abgleich mit dem Projekt-Review vom 11.10.2026 (`docs/reviews/2026-10-11-project-review.json`, Commit `834d38b`, liegt auf `feature/phasen-kopfzeile`). Der Lauf war ein Kalibrierungslauf, seine Befunde sind trotzdem einzeln geprüft. **16 der 21 Produktivcode-Punkte dieses Issues stehen dort als eigene Befunde** (quality/2, alle Low). Wer dieses Issue umsetzt, behebt sie mit. ## Abschnitt 1 — sicher tot | Punkt | Review-Befund | |---|---| | `TeamRequest` samt `TeamPlayerRequest` | — *(nicht im Bericht, siehe unten)* | | `OfficialRepository.findByClubIdAndFunction` | `QUAL-a99bdc` | | `VenueRepository.findByClubIdAndName` | `QUAL-fd4cbf` | | `UserClubMappingRepository.deleteByClubId` | `QUAL-cb7f0b` | | `GET /api/seasons/latest` (`getLatestSeason`) | `QUAL-4d6fb5` | | `seasonRepository` in `CsvImportService` | `QUAL-d5a5e9` | | `seasonRepository` in `LigaViewService` | `QUAL-fefdac` | | lokale Variable `hasPhone` (`PdfService`) | — *(nicht im Bericht)* | | `ScrapingResultResponse.clubsImported` | — *(nicht im Bericht)* | | `Roles.CAPTAIN` | **nicht mehr tot** — seit `b58cdb19` (10.10.) dreimal in `LoginTaskService` benutzt. Der Widerspruch zur eigenen Doku bleibt: 80 von 83 `@RolesAllowed` in `main` verwenden weiter Literale, nur drei `Roles.*` | ## Abschnitt 2 — nur Tests rufen auf | Punkt | Review-Befund | |---|---| | `PlayerRepository.findByNameAndClubId` | `QUAL-ea299e` | | `PlayerRepository.findByLicenseNumberAndClubId` | `QUAL-8dc20d` | | `EloSnapshotRepository.findByPlayerAndSeason` | `QUAL-65191d` | | `EloSnapshotRepository.findBySeasonOrdered` | `QUAL-80580f` | | `JwtService.isAdmin` | `QUAL-ce676c` | | `EloService.isCutoffReached` | `QUAL-2b8d13` | | `ArticleRepository.latestNews` | `QUAL-b415e2` | | `GameDayEntryRepository.deleteByClubId` | `QUAL-ba2dc1` | | `VenueRepository.deleteByClubId` | `QUAL-c04082` | | `RegistrationRepository.deleteByClubId` | `QUAL-54818a` | | `Validity.isOpen` | — *(im Lauf übersehen; der seither gebaute Sweep der Rubrik v12 findet ihn)* | | `TtvpCupBracket.participantsAt` | — *(ebenso)* | ## Abschnitt 3 — toter Testcode Nicht im Bericht: die Rubrik misst nur Produktivcode. Am heutigen Stand (`d8d816c`) weiter vorhanden: `TestSeasonNames`, `CupTestFixtures.staerksteMannschaft`. ## Was das Review nicht sieht `TeamRequest` (ein ganzer Typ), `hasPhone` (lokale Variable) und `clubsImported` (Record-Komponente) erfasst auch der neue Sweep nicht — er prüft Methoden, injizierte Felder und Endpunkte. Eingetragen im Rubrik-Backlog des Skills. Für dieses Issue ändert das nichts: die Punkte bleiben hier stehen. ## Im Review zusätzlich, nicht in diesem Issue Backend-Code, der zum Teil erst nach dem 03.10. entstanden ist: `TeamPlayerRepository.findOpenByTeamAndPlayer` (`QUAL-2ca5ea`), `EloResource.baselineRepository` (`QUAL-470157`), `GET /api/seasons/active/name` (`QUAL-ac1995`), `HalbseriePublicationService.isPublished` (`QUAL-55ed96`), `SeasonHalbserieService.halbserieOf` (`QUAL-544503`), `SeasonSetupService.ensureCategories` (`QUAL-9d9752`). `QUAL-0bdacc` (`GameDayEntryRepository.findAllValidAt`) ist ein Fehlalarm: der Aufrufer steht in `PublicClubResource`, die wegen eines rohen NUL-Bytes im Quelltext für `grep` unsichtbar ist.
Author
Collaborator

Umgesetzt und nach der technischen Abnahme in main (9bc2209): mvn -B clean verify 6334/6334, kein Schema-Drift, Portal 1324, E2E gegen Staging 214/214 (lauf403, f699121). Keine Migration, kein ADR — die Regel steht in CLAUDE.md unter Java: Kein Produktivcode nur für Tests.

Was mit den Abschnitten passiert ist

  • Abschnitt 1 und 3: gelöscht, wie vorgeschlagen — darunter TeamRequest und der Endpunkt GET /api/seasons/latest. Zwei Ausnahmen:
    • Roles.CAPTAIN ist seit b58cdb19 (10.10.) benutzt und bleibt. Dass @RolesAllowed fast überall Literale statt Roles.* verwendet, ist jetzt #116.
    • ScrapingResultResponse.clubsImported bleibt und wird im Portal angezeigt (Prüfschritte unten). Der Server zählt nur neu angelegte Vereine; bestehende benennt er still um, darum heisst 0 nicht „nichts passiert“.
  • Abschnitt 2: alle Methoden gelöscht, die nur noch Tests riefen; die Tests gehen jetzt den Weg der Produktion (findBySeasonAndPlayers, validTo == Validity.OPEN, findByClubIdAt usw.). Ausnahme Validity.isOpen: die Methode war nicht tot, sondern ungenutzt — dieselbe Prüfung stand im Produktivcode zweimal von Hand ausgeschrieben. Sie ersetzt jetzt diese beiden Stellen.
  • Beim Aufräumen mitgefallen: halbserieEnd, EloService.matchWeekRepository, JwtService.jwtParser.

PMD-Nebenbefunde bleiben

Die überflüssigen Klammern (TournamentResource, EloCutoffService) und der vereinfachbare Ternär (ArticleResource) sind kein toter Code, und die heutige Fassung liest sich besser: die Klammern zeigen, was zusammengehört, der Ternär nennt beide Fälle ausdrücklich. Der leere Catch in SeasonSeedService ist kommentiert und gewollt.

Prüfschritte (Staging, als Admin)

  1. Eine Datei vereine.csv anlegen mit dem Inhalt
    code,name
    ZZ99,Testverein Abnahme
    
  2. Portal → Verwaltung → Meldungen → Vereine importieren → die Datei wählen.
    Erwartet: Meldung „1 neuer Verein importiert“, der Verein steht in der Liste.
  3. Dieselbe Datei noch einmal importieren.
    Erwartet: „Keine neuen Vereine, bestehende aktualisiert“.
  4. Den Testverein über Löschen wieder entfernen.
Umgesetzt und nach der technischen Abnahme in `main` (`9bc2209`): `mvn -B clean verify` 6334/6334, kein Schema-Drift, Portal 1324, E2E gegen Staging 214/214 (`lauf403`, `f699121`). Keine Migration, kein ADR — die Regel steht in `CLAUDE.md` unter *Java*: **Kein Produktivcode nur für Tests.** ## Was mit den Abschnitten passiert ist - **Abschnitt 1 und 3:** gelöscht, wie vorgeschlagen — darunter `TeamRequest` und der Endpunkt `GET /api/seasons/latest`. Zwei Ausnahmen: - `Roles.CAPTAIN` ist seit `b58cdb19` (10.10.) benutzt und bleibt. Dass `@RolesAllowed` fast überall Literale statt `Roles.*` verwendet, ist jetzt #116. - `ScrapingResultResponse.clubsImported` bleibt und wird im Portal angezeigt (Prüfschritte unten). Der Server zählt nur **neu angelegte** Vereine; bestehende benennt er still um, darum heisst 0 nicht „nichts passiert“. - **Abschnitt 2:** alle Methoden gelöscht, die nur noch Tests riefen; die Tests gehen jetzt den Weg der Produktion (`findBySeasonAndPlayers`, `validTo == Validity.OPEN`, `findByClubIdAt` usw.). **Ausnahme `Validity.isOpen`:** die Methode war nicht tot, sondern ungenutzt — dieselbe Prüfung stand im Produktivcode zweimal von Hand ausgeschrieben. Sie ersetzt jetzt diese beiden Stellen. - Beim Aufräumen mitgefallen: `halbserieEnd`, `EloService.matchWeekRepository`, `JwtService.jwtParser`. ## PMD-Nebenbefunde bleiben Die überflüssigen Klammern (`TournamentResource`, `EloCutoffService`) und der vereinfachbare Ternär (`ArticleResource`) sind kein toter Code, und die heutige Fassung liest sich besser: die Klammern zeigen, was zusammengehört, der Ternär nennt beide Fälle ausdrücklich. Der leere Catch in `SeasonSeedService` ist kommentiert und gewollt. ## Prüfschritte (Staging, als Admin) 1. Eine Datei `vereine.csv` anlegen mit dem Inhalt ``` code,name ZZ99,Testverein Abnahme ``` 2. Portal → **Verwaltung → Meldungen** → **Vereine importieren** → die Datei wählen. Erwartet: Meldung **„1 neuer Verein importiert“**, der Verein steht in der Liste. 3. Dieselbe Datei noch einmal importieren. Erwartet: **„Keine neuen Vereine, bestehende aktualisiert“**. 4. Den Testverein über **Löschen** wieder entfernen.
Sign in to join this conversation.
No description provided.