Indywidualne Cenniki Rezerwacji (Individual Reservation Pricing)
1. Instrukcja Użytkownika (User Manual)
Cel i Wartość Biznesowa (Purpose & Business Value)
Moduł indywidualnych cenników rezerwacji pozwala administratorom na elastyczne definiowanie stawek dla wybranych klientów. Zamiast standardowych, globalnych cen przypisanych do obiektów lub typów zajęć, wybrany klient może otrzymać dedykowany cennik na rezerwacje (np. kortów).
Funkcja ta wspiera zarówno proste rabaty (np. stała niższa cena za godzinę), jak i zaawansowane reguły rozliczeniowe (np. inne stawki w weekendy, w określonych godzinach szczytu lub w wyznaczonych przedziałach dat).
Główne Funkcje (Key Features)
- Wybór trybu cennika: Na profilu użytkownika w zakładce Ustawienia administrator może włączyć indywidualną cenę rezerwacji i wybrać jeden z dwóch trybów:
- Podstawowy (Stała cena): Klient płaci stałą, określoną kwotę za każdą godzinę rezerwacji (np. zawsze 50 zł/h).
- Zaawansowany (Reguły cenowe): Pozwala na zdefiniowanie dynamicznych reguł, analogicznie do konfiguracji cenników typów zajęć.
- Kreator reguł zaawansowanych: W trybie zaawansowanym administrator może dodać wiele reguł określających:
- Zakresy dat obowiązywania reguły (np. sezon letni).
- Dni tygodnia (np. tylko weekendy).
- Przedziały godzinowe (np. godziny wieczorne od 16:00 do 22:00).
- Cenę obowiązującą w wybranym przedziale.
- Cena bazowa: W trybie zaawansowanym definiuje się również cenę bazową, która obowiązuje w okresach nieobjętych żadną szczegółową regułą.
2. Dokumentacja Techniczna (Technical Documentation)
Model Danych i Schemat Bazy (Data Model & Schema)
Ustawienia klienta są przechowywane w tabeli client_settings. Do obsługi zaawansowanych cenników dodano dwa nowe pola w ramach migracji 0114_add_individual_pricing_rules_to_client_settings.sql:
individual_reservation_pricing_type(TEXT, domyślnie'basic'): Określa tryb cennika ('basic'lub'advanced').individual_reservation_pricing_rules(TEXT, domyślnieNULL): Przechowuje reguły w formacie JSON (tablica obiektów typuPricingRule).
ALTER TABLE client_settings ADD COLUMN individual_reservation_pricing_type TEXT DEFAULT 'basic';
ALTER TABLE client_settings ADD COLUMN individual_reservation_pricing_rules TEXT DEFAULT NULL;
Przepływ Obliczania Ceny (Pricing Resolution Flow)
- Pobieranie ustawień: Metoda
getClientSettingsForUser(userEmail)pobiera z bazy danych rekord z tabeliclient_settingsi deserializuje reguły zapisane w formacie JSON do typuPricingRule[]. - Aplikowanie nadpisania ceny: W pliku
lib/utils/client-pricing.tsfunkcjaapplyClientPricingOverrideobsługuje kalkulację dla aktywności typubooking(rezerwacje):- Jeżeli klient ma ustawiony tryb
'advanced'i zdefiniowane reguły, system przypisuje te reguły do właściwościpricing_rulesobiektu wynikowego, a cenę bazową ustawia jakoprice. - Główny silnik wyliczania cen (
calculatePrice) przetwarza następnie te reguły w kontekście konkretnej daty i godziny rezerwacji, uwzględniając dni tygodnia oraz przedziały godzinowe. - Jeżeli klient ma ustawiony tryb
'basic', stosowana jest stała wartośćindividual_reservation_price.
- Jeżeli klient ma ustawiony tryb
Priorytety i Nadpisywanie (Precedence & Overrides)
W systemie obowiązuje następująca kolejność wyliczania stawek (od najwyższego priorytetu):
- Dedykowany cennik klienta dla konkretnego typu zajęć (tabela
client_pricing_rules) – jeśli zdefiniowano regułę dla danej aktywności i danego użytkownika, ma ona pierwszeństwo. - Indywidualny cennik rezerwacji klienta (ustawienia z tabeli
client_settings) – zaawansowane reguły lub cena podstawowa (tylko dla aktywności typubooking). - Standardowy cennik typu zajęć – cennik domyślny przypisany globalnie do rezerwacji/zajęć.
Testowanie i Atrapy SQLite (Testing & SQLite Mocks)
Ze względu na to, że testy integracyjne korzystają z lokalnych mocków bazy danych SQLite, w plikach testowych zdefiniowane są statyczne schematy tabel. Wszystkie mocki tabeli client_settings w poniższych plikach testowych zostały zaktualizowane o nowe kolumny:
- players.test.ts
- substitution.completePendingSubstitution.test.ts
- substitution.cancelGame.staffVsParticipant.test.ts
- substitution.cancelGame.test.ts
- players.getTasksData.test.ts
- game.enrollSkillAssessment.test.ts
- game.employeeRemoval.test.ts
Nowe przypadki testowe weryfikujące poprawność rozstrzygania reguł zostały dodane w dedykowanym pliku: