Dugout Value
Baseball research on pitching, hitting, and projections, plus tools for comparing players, contracts, and trade value.
Platzbuchung, Getränke und Mitgliederverwaltung des TC Muckensturm
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @dolli17OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
TCM App – Vereins-App des TC Muckensturm Ablösung der bisherigen eBuSy-Lösung durch eine eigene App für iOS, Android und Web. Rund 300 aktive Mitglieder, 8 Sandplätze. Fünf Zustände, jeder mit eigenem Riegel. Er gilt für jede Forderungsart gleich – Beitrag, Getränke, Arbeitsdienst, Gastgebühr:Read the full README ↗
Ablösung der bisherigen eBuSy-Lösung durch eine eigene App für iOS, Android und Web. Rund 300 aktive Mitglieder, 8 Sandplätze.
| Modul | Inhalt |
|---|---|
| Mitgliederverwaltung | Stammdaten, Mitgliedschaften, Rollen, Zahler-Beziehungen |
| Einstellungen | Alle Regelwerte im Admin-Dashboard änderbar |
| Freiplatzbuchung | 8 Plätze, 60-Minuten-Buchungen zur vollen oder halben Stunde, Serien-Blockungen |
| Getränkeabrechnung | Self-Service in der App und Kiosk-Tablet, monatliche Abrechnung |
| Beiträge & SEPA | Jahresbeitragslauf, Mandatsverwaltung, pain.008-Export |
| Arbeitsdienst | Soll-/Ist-Stunden, Ausgleich in Geld zum Jahresende |
Fünf Zustände, jeder mit eigenem Riegel. Er gilt für jede Forderungsart gleich – Beitrag, Getränke, Arbeitsdienst, Gastgebühr:
Forderung entsteht → Vorabankündigung → Lastschriftlauf → Datei → Rückläufer
charges.open .notified debit_items pain.008 .returned
Zwei Regeln tragen den Ablauf. Angekündigt und eingezogen wird je Zahler,
nicht je Forderung: ein Elternteil mit zwei Kindern liest eine Nachricht über den
Gesamtbetrag und sieht eine Buchung auf dem Kontoauszug. Und die
Vorabankündigungsfrist ist nicht umgehbar – sie hängt an der Forderung
(notified_at), wird bei der Auswahl geprüft und noch einmal im Trigger auf
debit_items; die direkten Schreibrechte auf beide Tabellen sind entzogen.
Wo die App endet: bei der fertigen .xml. Der Vorstand lädt sie im
Onlinebanking hoch; von der Bank kommt keine Rückmeldung. Rückläufer trägt
deshalb ein Mensch ein – über die EndToEndId, also genau das Feld, das ein
späterer camt-Import liefern würde.
apps/web Next.js – Mitglieder-Web, Admin-Dashboard, Kiosk-Route
apps/mobile Expo – Mitglieder-App für iOS und Android
packages/core Geschäftslogik, Zod-Schemas, generierte Datenbank-Typen
packages/ui geteilte Komponenten
supabase/ Migrationen, RLS-Policies, RPCs, Edge Functions, pgTAP-Tests
tools/import eBuSy-Import (läuft erst zum Cutover)
Doppelbuchungen sind durch die Datenbank ausgeschlossen, nicht durch Anwendungslogik:
alter table bookings add constraint bookings_no_overlap
exclude using gist (court_id with =, slot with &&)
where (status = 'active');
Zwei gleichzeitige Anfragen auf denselben Slot können nicht beide durchkommen – unabhängig davon, was der Client tut.
Buchungsregeln laufen serverseitig. Direkte Inserts auf bookings sind per RLS verboten;
der einzige Weg führt über die Funktion create_booking, die alle Regeln prüft – inklusive des
Kontingents jedes eingetragenen Mitspielers. Das Kontingent steht derzeit auf 0, also
unbegrenzt; die Regel bleibt vollständig im Code, damit der Vorstand sie in knappen Zeiten
über das Admin-Dashboard wieder einschalten kann.
Es gibt genau zwei Stufen: Admin und Mitglied. Admins sehen und ändern alles – Mitglieder, Beiträge, Serien, Einstellungen und jede fremde Buchung. Alle anderen sehen ihre eigenen Daten und verwalten ihre eigenen Buchungen bis zum Spielbeginn. Zwischenrollen (Kassenwart, Sportwart, Trainer, Thekendienst) gibt es bewusst nicht mehr: sie waren in einem Verein dieser Größe schwerer zu pflegen als sie nützten.
Der Belegungsplan zeigt volle Stunden von 08 bis 21 Uhr. Gebucht wird zur vollen oder halben Stunde, immer 60 Minuten – die Feinwahl passiert im Buchungsfenster. Eine Belegung sperrt jede Stunde, die sie berührt: das Dienstagstraining von 18:30 bis 20:00 wäre sonst im Stundenraster unsichtbar und der 18-Uhr-Platz sähe frei aus.
corepack enable pnpm
pnpm install
cp .env.example .env # ausfüllen
pnpm db:reset # Schema + synthetischer Testbestand
pnpm test # Unit- und Datenbanktests
pnpm test:functions # Edge Functions unter Deno (lädt Deno per pnpm dlx)
pnpm dev # Web-App
Das Web läuft als Docker-Container auf dem eigenen Server (187.124.4.243)
unter https://app.tennisclub-muckensturm.de, hinter dem dortigen Traefik.
Gearbeitet wird über Pull Requests: ein Merge auf main deployt Dev, ein
Merge auf production nach Freigabe Prod. Branches, Releases und Hotfixes
beschreibt CONTRIBUTING.md.
Abbild: apps/web/Dockerfile, Dienst: deploy/web/docker-compose.yml. Die
Werte (Domain, Supabase-URL und -Key) stehen auf dem Server in
/docker/tcm-web*/.env.
Die App unter apps/mobile liest ihre Supabase-Werte aus apps/mobile/.env
(EXPO_PUBLIC_SUPABASE_URL, EXPO_PUBLIC_SUPABASE_ANON_KEY) und startet mit
pnpm --filter @tcm/mobile ios. Wie sie in TestFlight kommt, steht in
apps/mobile/RELEASE.md.
Während der gesamten Entwicklung enthält die Datenbank ausschließlich synthetische Daten. Echte Mitgliederdaten kommen erst beim Cutover ins Spiel.
Die App verarbeitet Bankverbindungen und Geburtsdaten Minderjähriger. Vor dem Produktivgang
werden ein Verzeichnis von Verarbeitungstätigkeiten und ein AV-Vertrag mit Supabase (EU-Region)
benötigt. Zugangsdaten gehören ausschließlich in .env bzw. Supabase Vault – niemals ins Repo.