Dugout Value
투구·타격·예측 연구와 선수·계약·트레이드 가치를 비교하는 도구 제공
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
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: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.