feat: implement user linking for members and update database schema for user associations
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 53s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 53s
This commit is contained in:
146
docs/collective-orders-plan.md
Normal file
146
docs/collective-orders-plan.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Sammelbestellungen: gemeinsames Konzept für Club, Trainer und Trainingstagebuch
|
||||
|
||||
Stand: 2026-07-22
|
||||
|
||||
## Ziel
|
||||
|
||||
Eine Sammelbestellung bündelt Wünsche von Mitgliedern, Trainingsteilnehmern und
|
||||
Vereinsverantwortlichen. Club- und Trainerrollen steuern Bestellung, Preise,
|
||||
Rückfragen, Zahlung und Ausgabe; alle berechtigten Nutzer können Wünsche
|
||||
eintragen und ihren eigenen Stand nachvollziehen.
|
||||
|
||||
## Rollen und Rechte
|
||||
|
||||
| Aktion | Club | Trainer | Mitglied / Trainingstagebuch-Nutzer |
|
||||
| --- | --- | --- | --- |
|
||||
| Sammelbestellung anlegen | Ja | Ja | Nein |
|
||||
| Eigene Artikelwünsche eintragen | Ja | Ja | Ja |
|
||||
| Eigene Wünsche ändern oder stornieren, solange offen | Ja | Ja | Ja |
|
||||
| Preise, Bestellung, Ausgabe und Zahlungsstatus bearbeiten | Ja | Ja | Nein |
|
||||
| Rückfrage zu einem Artikel stellen | Ja | Ja | Nein |
|
||||
| Auf Rückfrage antworten | Ja | Ja | Ja, nur zum eigenen Artikel |
|
||||
| Preis bestätigen | Ja | Ja | Ja, nur zum eigenen Artikel |
|
||||
| Gesamtrechnung und Bestellstatus bearbeiten | Ja | Ja | Nein |
|
||||
|
||||
Der Ersteller einer Sammelbestellung erhält zusätzlich dieselben Steuerrechte
|
||||
wie Club/Trainer für genau diese Bestellung, auch wenn seine allgemeine Rolle
|
||||
später geändert wird.
|
||||
|
||||
## Datenmodell
|
||||
|
||||
### Sammelbestellung
|
||||
|
||||
- ID, `club_id`, Titel, Beschreibung, Lieferant, Bestellfrist
|
||||
- Ersteller (`created_by_user_id`), optional verantwortlicher Trainer
|
||||
- Bestellstatus: `open`, `ordered`, `arrived`
|
||||
- Zahlungsstatus: `unpaid`, `partially_paid`, `paid`
|
||||
- Gesamtrechnungsbetrag in Cent, Währung, Rechnungsreferenz
|
||||
- Zeitstempel für Bestellung, Eingang und Abschluss
|
||||
|
||||
### Artikelwunsch
|
||||
|
||||
- ID, Sammelbestellung, anfragender Nutzer und optional zugeordnetes Mitglied
|
||||
- Artikelname, Variante/Größe, Menge, Freitextwunsch
|
||||
- Einzelpreis in Cent, Währung
|
||||
- Artikelstatus: `entered`, `question`, `ordered`, `cancelled`, `arrived`, `issued`
|
||||
- Zahlungsstatus: `unpaid`, `paid`
|
||||
- Preisbestätigung durch den Anfragenden (`price_confirmed_at`)
|
||||
- Rückfrage: Text, gestellt von, gestellt am, Antwort, beantwortet am
|
||||
- Ausgabe: ausgegeben von, ausgegeben am
|
||||
|
||||
## Verbindliche Statuslogik
|
||||
|
||||
### Einzelartikel
|
||||
|
||||
1. `entered`: Wunsch wurde eingetragen.
|
||||
2. `question`: Verantwortliche stellen eine Rückfrage; der Nutzer kann antworten.
|
||||
3. `ordered`: Artikel ist beim Lieferanten bestellt.
|
||||
4. `cancelled`: Artikel wird nicht weitergeführt.
|
||||
5. `arrived`: Artikel ist eingetroffen.
|
||||
6. `issued`: Artikel wurde an den Nutzer ausgegeben.
|
||||
|
||||
Der Preis darf von Club/Trainer jederzeit bis zur Ausgabe gepflegt werden. Ist
|
||||
ein Einzelpreis vorhanden oder geändert, kann der Anfragende ihn bestätigen.
|
||||
Die Preisbestätigung ist für die Bestellung optional konfigurierbar, sollte aber
|
||||
vor `ordered` sichtbar als offen markiert sein.
|
||||
|
||||
Ein Artikel gilt nur dann als **abgeschlossen**, wenn sein Artikelstatus
|
||||
`issued` und sein Zahlungsstatus `paid` ist. Stornierte Artikel gelten als
|
||||
abgeschlossen, jedoch separat als storniert.
|
||||
|
||||
### Gesamte Sammelbestellung
|
||||
|
||||
- `open`: Wünsche werden gesammelt und geklärt.
|
||||
- `ordered`: Bestellung wurde ausgelöst.
|
||||
- `arrived`: Lieferung ist eingetroffen.
|
||||
|
||||
Der Zahlungsstatus bleibt unabhängig: `unpaid`, `partially_paid`, `paid`.
|
||||
Der Gesamtbetrag der Rechnung wird manuell gepflegt und steht neben der Summe
|
||||
aller Einzelpreise, damit Abweichungen sichtbar sind. Eine Bestellung ist erst
|
||||
abgeschlossen, wenn sie `arrived` ist und alle nicht stornierten Artikel
|
||||
ausgegeben und bezahlt sind.
|
||||
|
||||
## Ansichten
|
||||
|
||||
### Für alle Nutzer
|
||||
|
||||
- Liste offener und eigener Sammelbestellungen.
|
||||
- Wunschformular mit Artikel, Variante, Menge und Hinweis.
|
||||
- Eigene Artikel mit Preis, Preisbestätigung, Rückfrage und Status-Timeline.
|
||||
- Keine Sicht auf Wünsche, Preise oder Zahlungen anderer Nutzer.
|
||||
|
||||
### Club- und Traineransicht
|
||||
|
||||
- Neue Sammelbestellung anlegen und Verantwortliche festlegen.
|
||||
- Artikeltabelle mit Filtern: Status, Rückfrage offen, Preis unbestätigt,
|
||||
unbezahlt, eingetroffen, auszugeben.
|
||||
- Preis, Artikelstatus, Rückfrage und Zahlungsstatus inline pflegen.
|
||||
- Gesamtstatus, Gesamtrechnung und Gesamtzahlungsstatus pflegen.
|
||||
- Übersichten für fehlende Preisbestätigungen, offene Rückfragen und noch
|
||||
auszugebende Artikel.
|
||||
|
||||
### Trainingstagebuch
|
||||
|
||||
- Kontextlink aus einer Trainingseinheit auf aktive Sammelbestellungen.
|
||||
- Teilnehmer können dort ihren Wunsch eintragen oder den eigenen Status prüfen.
|
||||
- Keine Finanz- oder Verwaltungsaktionen für normale Teilnehmer.
|
||||
|
||||
## Umsetzungstodos
|
||||
|
||||
### Phase 1: Grundlage und Rechte
|
||||
|
||||
- [ ] Datenmodell, Migrationen und Indizes für Bestellung und Artikelwunsch anlegen.
|
||||
- [ ] Berechtigung `collective_orders` mit read/write und Ersteller-Ausnahme definieren.
|
||||
- [ ] Sichere Zuordnung User ↔ Mitglied für eigene Wünsche verbindlich klären.
|
||||
- [ ] REST-Endpunkte für Liste, Detail, Bestellung und eigene Artikelwünsche erstellen.
|
||||
- [ ] Statusübergänge serverseitig validieren.
|
||||
|
||||
### Phase 2: Club- und Trainer-Arbeitsbereich
|
||||
|
||||
- [ ] Bestellliste und Detailansicht implementieren.
|
||||
- [ ] Bestellung anlegen, Gesamtbetrag und Gesamtstatus pflegen.
|
||||
- [ ] Artikelstatus, Einzelpreis und Zahlungsstatus pflegen.
|
||||
- [ ] Rückfrage-/Antwort-Workflow und Preisbestätigung umsetzen.
|
||||
- [ ] Abschlusslogik und Arbeitsfilter umsetzen.
|
||||
|
||||
### Phase 3: Mitglieder- und Trainingstagebuch-Sicht
|
||||
|
||||
- [ ] Eigene Wünsche eintragen, ändern und stornieren.
|
||||
- [ ] Eigene Rückfragen beantworten und Preise bestätigen.
|
||||
- [ ] Persönliche Statusanzeige und verständliche leere Zustände bauen.
|
||||
- [ ] Kontextlink aus Trainingstagebuch ergänzen.
|
||||
|
||||
### Phase 4: Abgleich und Qualität
|
||||
|
||||
- [ ] Abweichung zwischen Gesamtrechnung und Summe der Artikelpreise sichtbar machen.
|
||||
- [ ] Export für Lieferant, Ausgabe und offene Zahlungen ergänzen.
|
||||
- [ ] Rechte-, Status- und Mobil-Smoketests mit Club, Trainer und Mitglied durchführen.
|
||||
- [ ] Historie und Archivverknüpfung für abgeschlossene Bestellungen ergänzen.
|
||||
|
||||
## Abnahmekriterien
|
||||
|
||||
- [ ] Mitglieder können ausschließlich eigene Wünsche und Rückfragen sehen.
|
||||
- [ ] Club/Trainer können jeden Artikel vollständig steuern.
|
||||
- [ ] Kein Artikel wird als abgeschlossen markiert, bevor er ausgegeben und bezahlt ist.
|
||||
- [ ] Gesamtbetrag und Artikelpreissumme sind transparent vergleichbar.
|
||||
- [ ] Offene Rückfragen, unbestätigte Preise, fehlende Zahlungen und Ausgaben sind mit einem Filter erreichbar.
|
||||
@@ -18,6 +18,21 @@ Ergaenzend:
|
||||
|
||||
## 2026-07-22
|
||||
|
||||
### `member.user_id`
|
||||
|
||||
Sichere optionale Zuordnung eines Login-Kontos zu einem Vereinsmitglied für
|
||||
persönliche Mitgliederfunktionen:
|
||||
|
||||
```sql
|
||||
ALTER TABLE member
|
||||
ADD COLUMN user_id INT NULL,
|
||||
ADD UNIQUE KEY member_user_id_unique (user_id),
|
||||
ADD CONSTRAINT member_user_id_fk FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE SET NULL;
|
||||
```
|
||||
|
||||
Bestehende Mitglieder bleiben zunächst unverknüpft. Die Zuordnung erfolgt
|
||||
bewusst über die Verwaltungs-API und nicht über einen automatischen E-Mail-Abgleich.
|
||||
|
||||
### `club_communication_threads.reply_to`
|
||||
|
||||
Optionale Antwortadresse je Kommunikationsvorgang:
|
||||
|
||||
83
docs/simple-user-plan.md
Normal file
83
docs/simple-user-plan.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Einfache Nutzer: Produkt- und Umsetzungsplan
|
||||
|
||||
Stand: 2026-07-22
|
||||
|
||||
## Zielgruppe und Zielbild
|
||||
|
||||
Einfache Nutzer sind Vereinsmitglieder oder Helfer ohne Verwaltungsauftrag. Sie
|
||||
sollen persönliche Informationen finden und Rückmeldungen geben können, ohne
|
||||
Finanzen, Rollenverwaltung, Archiv oder interne Vorgänge zu sehen.
|
||||
|
||||
## Rechteprinzip
|
||||
|
||||
- Kein Zugriff auf Finanzen, Rollen, Benutzerverwaltung, Archiv oder Historie.
|
||||
- Nur eigene bzw. explizit freigegebene Vereinsdaten sehen.
|
||||
- Eigene Angaben und Rückmeldungen bearbeiten; vereinsweite Änderungen bleiben
|
||||
bei Verwaltungsrollen.
|
||||
|
||||
## Umsetzung in sinnvoller Reihenfolge
|
||||
|
||||
### Phase 1: Zugang und persönlicher Einstieg
|
||||
|
||||
- [ ] Rollenprofil `member` und Navigation gegen unzulässige Ziele auditieren.
|
||||
- [ ] Persönliches Dashboard für Termine, Training, Rückmeldungen und Vereinsnachrichten umsetzen.
|
||||
- [ ] Leere Zustände für fehlende Termine, Nachrichten und Rückmeldungen formulieren.
|
||||
- [ ] Persönliche Startseite als Standardziel nach Login festlegen.
|
||||
|
||||
Abnahme:
|
||||
|
||||
- [ ] Ein Nutzer ohne Verwaltungsrechte sieht nur seinen persönlichen Bereich.
|
||||
- [ ] Kein sichtbarer Link führt zu einer anschließenden Berechtigungsfehlermeldung.
|
||||
|
||||
### Phase 2: Eigene Daten und Rückmeldungen
|
||||
|
||||
- [ ] Ansicht „Mein Profil“ für freigegebene Stammdaten bereitstellen.
|
||||
- [ ] Änderungsanfrage für Kontaktdaten statt direkter Änderung geschützter Felder umsetzen.
|
||||
- [ ] Zu- und Absagen für relevante Trainings oder Veranstaltungen ermöglichen.
|
||||
- [ ] Mitgliedschafts- und SEPA-Hinweise verständlich, aber ohne sensible Zahlungsdaten anzeigen.
|
||||
- [ ] Rückmeldungen für berechtigte Verantwortliche sichtbar machen.
|
||||
|
||||
Abnahme:
|
||||
|
||||
- [ ] Kontaktdaten können sicher geändert bzw. zur Prüfung eingereicht werden.
|
||||
- [ ] Zu- und Absagen sind an der jeweiligen Veranstaltung nachvollziehbar.
|
||||
|
||||
### Phase 3: Kommunikation und Informationen
|
||||
|
||||
- [ ] Persönlichen Nachrichteneingang bereitstellen.
|
||||
- [ ] Vereinsankündigungen nach Datum sortiert anzeigen.
|
||||
- [ ] Gelesen-/ungelesen-Status und einen klaren Rückfrageweg ergänzen.
|
||||
- [ ] Datenschutz- und Sichtbarkeitsregeln für Nachrichten und Kontaktinformationen prüfen.
|
||||
|
||||
Abnahme:
|
||||
|
||||
- [ ] Neue Vereinsinformationen sind ohne Verwaltungsmenüs auffindbar.
|
||||
- [ ] Persönliche Nachrichten sind ausschließlich für den Empfänger sichtbar.
|
||||
|
||||
### Phase 4: Mobil, Qualität und Einführung
|
||||
|
||||
- [ ] Mobilansicht und langsame Verbindungen prüfen.
|
||||
- [ ] Berechtigungstest mit Mitglied, Trainer und Vorstand durchführen.
|
||||
- [ ] Onboarding für ersten Login, Profilprüfung und Rückmeldungen erstellen.
|
||||
- [ ] Pilot mit wenigen echten Mitgliedern durchführen und Feedback auswerten.
|
||||
|
||||
Abnahme:
|
||||
|
||||
- [ ] Die Testrollen sehen jeweils nur die vorgesehenen Daten und Aktionen.
|
||||
- [ ] Der persönliche Hauptablauf funktioniert auf Mobilgeräten ohne Hilfestellung.
|
||||
|
||||
## Nicht Teil dieses Plans
|
||||
|
||||
- Vereinsverwaltung, Buchhaltung, Rollenpflege und Archivarbeit.
|
||||
- Erweiterungen des Player-Produkts `mein-tt.de`; diese bleiben in der eigenen
|
||||
[mein-tt.de-Roadmap](./mein-tt-product-plan.md).
|
||||
|
||||
## Erste umsetzbare Tickets
|
||||
|
||||
1. [ ] Bestehende `member`-Berechtigungen und Navigation auditieren.
|
||||
2. [ ] Datenvertrag und Wireframe für das persönliche Dashboard festlegen.
|
||||
3. [ ] Dashboard mit Terminen und Nachrichten implementieren.
|
||||
4. [ ] Profil- und Kontaktdaten-Änderungsanfrage implementieren.
|
||||
5. [ ] Trainings- und Veranstaltungsrückmeldungen ergänzen.
|
||||
6. [ ] Nachrichteneingang und Benachrichtigungsstatus ergänzen.
|
||||
7. [ ] Rollen- und Mobile-Smoke-Test mit Pilotgruppe durchführen.
|
||||
@@ -1,9 +0,0 @@
|
||||
# HTTP: www.tt-club.de und tt-club.de -> HTTPS
|
||||
<VirtualHost *:80>
|
||||
ServerName www.tt-club.de
|
||||
Redirect permanent / https://tt-club.de/
|
||||
</VirtualHost>
|
||||
<VirtualHost *:80>
|
||||
ServerName tt-club.de
|
||||
Redirect permanent / https://tt-club.de/
|
||||
</VirtualHost>
|
||||
16
docs/tt-verein.de-bootstrap.conf
Normal file
16
docs/tt-verein.de-bootstrap.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
# Temporärer HTTP-VHost für die erstmalige Let's-Encrypt-Ausstellung.
|
||||
# Diese Datei vor dem Zertifikat als tt-verein.de.conf aktivieren.
|
||||
<VirtualHost *:80>
|
||||
ServerName tt-verein.de
|
||||
ServerAlias www.tt-verein.de
|
||||
|
||||
DocumentRoot /var/www/tt-tagebuch.de
|
||||
<Directory /var/www/tt-tagebuch.de>
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
ErrorLog ${APACHE_LOG_DIR}/tt-verein.de_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/tt-verein.de_access.log combined
|
||||
</VirtualHost>
|
||||
@@ -1,18 +1,18 @@
|
||||
# tt-verein.de nutzt dieselbe ausgerollte Anwendung wie tt-tagebuch.de.
|
||||
<VirtualHost *:443>
|
||||
ServerName tt-club.de
|
||||
ServerAlias www.tt-club.de
|
||||
# tt-club.de nutzt dieselbe ausgerollte Anwendung wie tt-tagebuch.de.
|
||||
ServerName tt-verein.de
|
||||
ServerAlias www.tt-verein.de
|
||||
DocumentRoot /var/www/tt-tagebuch.de
|
||||
<Directory /var/www/tt-tagebuch.de>
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
ErrorLog ${APACHE_LOG_DIR}/tt-club.de_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/tt-club.de_access.log combined
|
||||
ErrorLog ${APACHE_LOG_DIR}/tt-verein.de_error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/tt-verein.de_access.log combined
|
||||
SSLEngine on
|
||||
SSLCertificateFile /etc/letsencrypt/live/tt-club.de/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/tt-club.de/privkey.pem
|
||||
SSLCertificateFile /etc/letsencrypt/live/tt-verein.de/fullchain.pem
|
||||
SSLCertificateKeyFile /etc/letsencrypt/live/tt-verein.de/privkey.pem
|
||||
Include /etc/letsencrypt/options-ssl-apache.conf
|
||||
ProxyRequests Off
|
||||
ProxyPass /api http://localhost:3050/api
|
||||
9
docs/tt-verein.de.conf
Normal file
9
docs/tt-verein.de.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# HTTP: www.tt-verein.de und tt-verein.de -> HTTPS
|
||||
<VirtualHost *:80>
|
||||
ServerName www.tt-verein.de
|
||||
Redirect permanent / https://tt-verein.de/
|
||||
</VirtualHost>
|
||||
<VirtualHost *:80>
|
||||
ServerName tt-verein.de
|
||||
Redirect permanent / https://tt-verein.de/
|
||||
</VirtualHost>
|
||||
Reference in New Issue
Block a user