Przejdź do głównej zawartości

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):

  1. 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).
  2. Indywidualny cennik rezerwacji klienta: Zdefiniowany z poziomu ustawień klienta (omawiany w niniejszym dokumencie). Wykorzystywany głównie podczas rezerwacji wolnych kortów.
  3. 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 JSON PricingRule[].

Algorytm nakładania stawek (Pricing Resolution Flow)

  1. Pobieranie ustawień klienta: Metoda getClientSettingsForUser(userEmail) pobiera wiersz usera.
  2. Override ceny zniżkowej: W lib/utils/client-pricing.ts odpala się funkcja applyClientPricingOverride. W przypadku obiektu o aktywności typu booking:
    • Jeśli mode advanced, funkcja nadpisuje klucz pricing_rules obiekcie bazowym zajęć na reguły JSON od usera. Następnie stary i znany core-pricing silnik calculatePrice przetwarza to tak samo, jakby liczył zwykłe reguły cennika (biorąc pod uwagę timezone, daty zajęć i overlap godzin).
    • Jeśli mode basic, system po prostu ucina wszystkie oryginalne reguły i wstawia twarde price: user_price_amount.

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.ts
  • lib/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).