Indywidualne Cenniki Rezerwacji
Instrukcja ustawiania specjalnych cenników na wynajem kortów (i innych rezerwacji) dla konkretnych, wybranych klientów.
👤 Instrukcja dla pracownika (Administracja)
System umożliwia zdefiniowanie indywidualnej stawki za wynajem kortu dla wybranych uczestników (np. stałych klientów lub partnerów zewnętrznych). Konfiguracja ta pozwala na nadpisanie standardowych cenników obiektowych dla określonego profilu użytkownika.
Poniżej przedstawiono procedurę konfiguracji:
1. Wybór klienta i trybu
Ścieżka dla pracownika: Dashboard ➔ Uczestnicy ➔ Wyszukaj klienta ➔ Karta "Ustawienia" ➔ Sekcja "Indywidualny cennik rezerwacji"
System obsługuje dwa tryby konfiguracji cennika indywidualnego:
- Tryb podstawowy (Stała cena): Definiuje jedną, stałą stawkę godzinową wynajmu (np. 50 zł/h). Kwota ta obowiązuje bezwzględnie, niezależnie od dnia tygodnia czy pory dnia.
- Tryb zaawansowany (Reguły godzinowe/dniowe): Funkcjonuje na analogicznych zasadach co zaawansowane cenniki obiektowe. Pozwala na konfigurację zmiennych stawek w zależności od wybranych dni tygodnia lub przedziałów godzinowych.
2. Budowa zaawansowanego cennika indywidualnego
W przypadku wyboru trybu zaawansowanego, w pierwszej kolejności należy określić Cenę bazową. Stanowi ona stawkę domyślną w momentach, gdy żadna z dodatkowych reguł nie ma zastosowania.
Następnie administrator może definiować reguły będące wyjątkami, określając w nich:
- Zakresy dat: (np. zniżka sezonowa w okresie zimowym).
- Dni tygodnia: (np. preferencyjna stawka obowiązująca wyłącznie w weekendy).
- Przedziały godzinowe: (np. wyższa stawka w godzinach szczytu, od 16:00 do 22:00, poza którymi obowiązuje cena bazowa).
Priorytetyzacja cenników
Architektura systemu przydziela cennikom określoną hierarchię ważności. Algorytm ustala stawkę końcową według następującej kolejności (od najwyższego do najniższego priorytetu):
- Dedykowany cennik uczestnika w konkretnych zajęciach: Konfiguracja określona bezpośrednio w edycji wybranej grupy zdjęciowej (np. wyjątek w szkółce przypisany do konkretnego klienta).
- Indywidualny cennik rezerwacji klienta: Zdefiniowany z poziomu ustawień klienta (omawiany w niniejszym dokumencie). Wykorzystywany głównie podczas rezerwacji wolnych kortów.
- Standardowy cennik obiektu: Bazowa konfiguracja cennika przypisana do rodzaju zajęć lub obiektu.
Dzięki przyjętej hierarchii, klient posiadający aktywny cennik indywidualny automatycznie korzysta z preferencyjnych stawek w Portalu Klienta, podczas gdy standardowi użytkownicy podlegają cennikowi ogólnemu.
🛠️ Dokumentacja techniczna
Szczegóły logiki backendowej wyliczania zniżek.
Model i schemat bazy (Data Model & Schema)
Ustawienia poszczególnych klientów (w tym stawki per-user) trzymane są w tabeli client_settings. Migracja powiązana: 0114_add_individual_pricing_rules_to_client_settings.sql:
individual_reservation_pricing_type(TEXT): Wartości'basic'lub'advanced'.individual_reservation_pricing_rules(TEXT, null): Zserializowana struktura JSONPricingRule[].
Algorytm nakładania stawek (Pricing Resolution Flow)
- Pobieranie ustawień klienta: Metoda
getClientSettingsForUser(userEmail)pobiera wiersz usera. - Override ceny zniżkowej: W
lib/utils/client-pricing.tsodpala się funkcjaapplyClientPricingOverride. W przypadku obiektu o aktywności typubooking:- Jeśli mode
advanced, funkcja nadpisuje kluczpricing_rulesobiekcie bazowym zajęć na reguły JSON od usera. Następnie stary i znany core-pricing silnikcalculatePriceprzetwarza to tak samo, jakby liczył zwykłe reguły cennika (biorąc pod uwagę timezone, daty zajęć ioverlapgodzin). - Jeśli mode
basic, system po prostu ucina wszystkie oryginalne reguły i wstawia twardeprice: user_price_amount.
- Jeśli mode
Pokrycie w testach
Zmiany modelu bazy dla testów integracyjnych z mockami sqlite (używanych w Vitest) zostały umieszczone w stałych schematach bazy mocków we wszystkich testach dotyczących mutacji usera i gry, np.:
lib/actions/players.test.tslib/actions/substitution.completePendingSubstitution.test.ts__tests__/lib/utils/client-pricing.test.ts(dedykowane testy pokrywające edge-case'y przecinania się reguł VIP-owskich ze standardowymi).