Przejdź do głównej zawartości

Typ uczestnika (user_type)

Każdy uczestnik ma w bazie typ — informację, czy jest w klubie nowy, czy wraca po przerwie, i czy sam trenuje, czy jest opiekunem. Ta jedna kolumna decyduje o dwóch rzeczach widocznych na co dzień: czy uczestnik może się zapisać na zajęcia próbne i czy pojawia się na tablicy zadań jako klient do obsłużenia.

👤 Instrukcja dla recepcji i biura

Co widzi klient

W oknie Zapisz się ➔ Zajęcia próbne klient wybiera uczestnika z listy. Uczestnik, który nie może być zapisany, jest wyszarzony i ma przy sobie powód:

KomunikatCo oznacza
Był(a) już na zajęciach próbnychPróbne są za nim — odbyte, opłacone albo już umówione
Zajęcia próbne niedostępne — napisz na [email protected]Uczestnik nie ma ustawionego typu, więc system nie wie, kim jest
Zaległe płatnościKonto opiekuna jest zawieszone do czasu uregulowania zaległości
Trener nie przydzielił jeszcze grupyPróbne odbyte, czekamy na decyzję trenera

Drugi komunikat to nie jest normalny stan. Oznacza brak typu i wymaga poprawienia rekordu — klient sam sobie z tym nie poradzi.

Skąd bierze się brak typu

Historycznie kilka ścieżek zakładało uczestnika bez pytania o typ: dopisanie uczestnika przez recepcję z poziomu grafiku, zapisy na półkolonie i kursy tenisa oraz konta lokalne zakładane na miejscu. Takie rekordy trafiały do bazy z pustym typem i wypadały zarówno z zapisów na próbne, jak i z tablicy zadań — nikt w klubie ich nie widział, a klient nie mógł się zapisać.

Od migracji 0255 wszystkie te ścieżki ustawiają Nowy uczestnik, a istniejące rekordy zostały poprawione. Jeśli mimo to trafisz na uczestnika z tym komunikatem, ustaw mu typ w profilu uczestnika — wtedy zapis od razu się odblokuje.

Trenerzy to wyjątek

Trener ma własny rekord uczestnika (żeby dało się go rezerwować), ale celowo bez typu. Dzięki temu nie pojawia się na tablicy zadań jako lead i nie dostaje propozycji zajęć próbnych. Nie ustawiaj trenerowi typu uczestnika.

🛠 Dokumentacja techniczna

Model danych

Kolumna player.user_type przyjmuje sześć wartości plus NULL:

WartośćZnaczenie
newParticipantNowy, trenuje sam
newGuardianNowy, jest opiekunem
newParticipantAndGuardianNowy, trenuje i jest opiekunem
returningParticipantPowracający, trenuje sam
returningGuardianPowracający, opiekun
returningParticipantAndGuardianPowracający, trenuje i opiekun
NULLRekord trenera — świadomy wyjątek

Gdzie jest czytana

MiejsceZachowanie przy NULL
getTrialEnrollmentStatus (shouldPlayerEnrollSkillAssessment.ts)blockedBy: 'notEligible' → wyszarzony wiersz w wyborze uczestnika
getPlayersWithoutActivityTypeAndGame (players.ts)Uczestnik nie trafia na tablicę zadań
Filtr participantType na liście uczestnikówUczestnik nie pasuje ani do „nowych", ani do „powracających"
getDefaultActivityStatus w createPlayerStatus aktywny (jak dla uczestnika, nie opiekuna)

Bramka próbnych sprawdza typ jako pierwszy warunek, przed płatnościami i zapisami, więc NULL blokuje zapis niezależnie od reszty historii uczestnika. Panel pracownika tej bramki nie używa — recepcja może zapisać na próbne każdego, co przez długi czas maskowało problem.

Wartość domyślna

createPlayer rozróżnia brak pola od jawnego null:

  • pole pominięte → newParticipant (uczestnik jest nowy, dopóki klub nie ustali inaczej),
  • user_type: null → zapis NULL, wyłącznie dla rekordów trenerów (lib/instructor-player.ts).

Dzięki temu nowa ścieżka tworzenia uczestnika nie może już przez przeoczenie wyprodukować rekordu bez typu.

Migracja naprawcza

migrations/0255_backfill_player_user_type.sql ustawia newParticipant wszystkim rekordom z user_type IS NULL i is_instructor = 0, łącznie z zarchiwizowanymi — przywrócenie takiego rekordu nie przywraca usterki. Migracja jest idempotentna: ponowne uruchomienie nie ma już czego poprawić.

Skutek uboczny do zaplanowania z klubem: uczestnicy bez grupy i bez zajęć, którzy wcześniej byli niewidoczni, pojawiają się na tablicy zadań jako leady do obsłużenia.

Powiązane dokumenty