Files
trainingstagebuch/docs/friendly-match-shared-concept-plan.md
Torsten Schulz (local) 0ff67dae80
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 49s
Implement cross-club friendly match concept with invitations and shared matches
- Added controllers for handling friendly match invitations and shared matches.
- Created migration scripts for `friendly_match_invitation` and `friendly_match_shared` tables.
- Developed models for `FriendlyMatchInvitation` and `FriendlyMatchShared`.
- Established routes for managing invitations and shared matches.
- Implemented services for business logic related to invitations and shared matches.
- Documented the concept plan for the new feature including API endpoints and data models.
2026-05-30 17:50:35 +02:00

6.4 KiB

Konzeptplan: Vereinsuebergreifende Freundschaftsspiele

Ziel

  • Ein gemeinsames Freundschaftsspiel-Objekt fuer zwei Vereine (statt zwei isolierter Eintraege).
  • Auffindbarkeit bestehender Spiele ueber Name, Datum und Startzeit.
  • Einladungsprozess (anbieten, annehmen, ablehnen).
  • Live-Synchronisierung zwischen beiden Vereinen per Socket.

Produktumfang (MVP)

  • Vereinsuebergreifendes Shared-Match-Datenmodell einfuehren.
  • Match-Finder fuer Name, Datum, Startzeit implementieren.
  • Einladung erstellen (Zielverein aus Vereinsliste + Freitext).
  • Einladung im System speichern.
  • E-Mail-Benachrichtigung an hinterlegte Personen des Zielvereins versenden.
  • Einladung annehmen: Shared-Match fuer beide Vereine erstellen.
  • Einladung ablehnen: Einladung loeschen.
  • Socket-Sync fuer beide Vereine bei Aenderungen am Shared-Match.

Datenmodell

Neue Tabellen

  • friendly_match_shared
    • id
    • home_club_id
    • guest_club_id
    • date
    • start_time
    • match_name (oder Home/Gast-Namenstruktur)
    • location_* Felder
    • match_system, singles_count, doubles_count, winning_sets
    • home_participants, guest_participants
    • result_details, home_match_points, guest_match_points
    • is_completed
    • created_by_user_id
    • created_from_invitation_id
    • created_at, updated_at
  • friendly_match_invitation
    • id
    • from_club_id
    • to_club_id
    • proposed_date
    • proposed_start_time
    • proposed_match_name
    • message (Freitext)
    • status (pending, accepted)
    • created_by_user_id
    • created_at, updated_at

Indizes und Constraints

  • Index auf friendly_match_shared (home_club_id, date, start_time).
  • Index auf friendly_match_shared (guest_club_id, date, start_time).
  • Index auf friendly_match_invitation (to_club_id, status, proposed_date).
  • Verhindern, dass ein Verein sich selbst einlaedt (from_club_id != to_club_id).

Backend API

Finder

  • GET /api/friendly-matches/find
    • Query-Parameter: clubId, name, date, startTime.
    • Exakt-Matches und Kandidaten mit confidence zurueckgeben.

Einladungen

  • POST /api/friendly-match-invitations/:clubId
    • Payload: toClubId, date, startTime, matchName, message.
  • GET /api/friendly-match-invitations/:clubId/incoming
  • GET /api/friendly-match-invitations/:clubId/outgoing
  • POST /api/friendly-match-invitations/:clubId/:invitationId/accept
  • POST /api/friendly-match-invitations/:clubId/:invitationId/decline

Shared Matches

  • GET /api/friendly-matches/shared/:clubId
  • PUT /api/friendly-matches/shared/:clubId/:matchId
  • PATCH /api/friendly-matches/shared/:clubId/:matchId/players
  • Optional: DELETE /api/friendly-matches/shared/:clubId/:matchId

Rechte und Zugriff

  • Zugriff pruefen: User muss in beteiligtem Verein freigeschaltet sein.
  • Schreibrechte auf Shared-Match nur mit schedule.write.
  • Einladung annehmen/ablehnen nur fuer to_club_id.

E-Mail-Versand

  • Empfaengerermittlung: user_club (approved=true) + user.email fuer Zielverein.
  • Neue Mailfunktion in emailService fuer Einladung.
  • Inhalt: einladender Verein, Matchdaten, Freitext, Aktion (annehmen/ablehnen in App).
  • Fehlerbehandlung: Einladung bleibt erhalten, falls Mailversand fehlschlaegt (mit Log).

Matching-Logik (Name/Datum/Startzeit)

  • Normalisierung von Namen (trim, lowercase, Sonderzeichenbereinigung).
  • Datum exakt matchen.
  • Startzeit exakt matchen (MVP).
  • Teamnamen in beide Richtungen pruefen (home/guest vertauscht).
  • confidence-Stufen definieren (exact, high, medium).

Socket-Sync

  • Neue Socket-Events definieren:
    • friendly:invitation:created
    • friendly:invitation:accepted
    • friendly:invitation:declined
    • friendly:shared:match:updated
    • friendly:shared:match:deleted
  • Bei Shared-Match-Aenderung an beide Club-Raeume senden (club-<home>, club-<guest>).
  • Frontend und Mobile auf neue Events subscriben.

Frontend (Web)

  • Bereich "Einladungen" (Eingehend/Ausgehend) in Freundschaftsspielen.
  • Dialog "Verein einladen": Zielverein aus bestehender Vereinsliste + Freitext.
  • Buttons fuer annehmen/ablehnen in eingehenden Einladungen.
  • Finder-UI fuer Name/Datum/Startzeit.
  • Shared-Match-Kennzeichnung in Liste und Detaildialog.
  • Socket-Event-Handling fuer Echtzeitupdates beider Vereine.

Mobile (Android + Shared)

  • API-Endpoints in MatchesApi erweitern.
  • State-Manager fuer Einladungen und Shared-Matches erweitern.
  • UI fuer Einladungen (eingehend/ausgehend) einbauen.
  • Finder-UI fuer Name/Datum/Startzeit einbauen.
  • Shared-Match-Bearbeitung fuer beide Vereine synchronisieren.
  • Socket-Events fuer Friendly-Shared-Flow verarbeiten.

Migration und Abwaertskompatibilitaet

  • Bestehende friendly_match-Eintraege unveraendert weiter lesbar halten.
  • Schrittweise Migration/Koexistenzstrategie dokumentieren.
  • Optionales Mapping alter Einzel-Eintraege auf Shared-Matches definieren.

Tests

Backend

  • Unit-Tests fuer Match-Finder.
  • Unit-Tests fuer Einladung (create/accept/decline).
  • Integrations-Tests fuer Shared-Match-CRUD.
  • Berechtigungstests (falscher Verein, fehlende Rechte).

Frontend/Mobile

  • UI-Tests fuer Einladung erstellen/anzeigen/entscheiden.
  • UI-Tests fuer Finder.
  • Realtime-Tests mit zwei gleichzeitig eingeloggten Vereinen.

End-to-End

  • Verein A laedt Verein B ein.
  • E-Mail wird versendet.
  • Verein B nimmt an, Shared-Match entsteht.
  • Aenderung in Verein A erscheint sofort in Verein B und umgekehrt.
  • Ablehnung loescht Einladung vollstaendig.

Rollout in Phasen

  • Phase 1: Datenmodell + Read-APIs.
  • Phase 2: Einladung + E-Mail.
  • Phase 3: Accept/Decline + Shared-Match-Erzeugung.
  • Phase 4: Shared-Match-Edit + Socket-Sync.
  • Phase 5: Finder + UX-Polish + E2E-Hardening.

Offene Entscheidungen

  • Mehrfache parallele Einladungen fuer gleiche Daten erlauben oder verhindern?
  • Match-Name als einzelnes Feld oder Home/Gast getrennt fuehren?
  • Konfliktstrategie bei gleichzeitiger Bearbeitung (Last-Write-Wins vs. Versionierung)?
  • Ablehnung immer hard delete oder auditierbar speichern?