Raporty finansowe i transakcje
Instrukcja dotycząca zakładki Finanse w systemie. Znajdziesz tu informacje o tym, jak system zlicza wpłaty od klientów i jak ułatwia rozliczanie kasy na koniec zmiany.
👤 Instrukcja dla pracownika
Zakładka Finanse (dostępna w głównym menu) służy do monitorowania wszystkich przychodów obiektu. Pozwala na łatwe podsumowanie zmiany i sprawdzenie, ile pieniędzy wpłynęło gotówką, a ile kartą lub przelewami online.
1. Grupowanie transakcji (Jedna wpłata = Jeden wiersz)
W systemie wdrożyliśmy ułatwienie polegające na grupowaniu płatności. Co to oznacza dla Ciebie?
- Kiedyś, jeśli klient płacił z góry za 4 lekcje w miesiącu, system pokazywał to jako 4 osobne wpłaty na liście.
- Obecnie: Jeśli klient zapłacił za cały pakiet jedną kartą, w kasie, jednym przelewem lub otrzymał na to jedną fakturę – zobaczysz to w zakładce Finanse jako jeden wiersz.
- W opisie takiej płatności zobaczysz skrót, np.
Zajęcia: Szkoła (x4). - Dzięki temu liczba transakcji w systemie idealnie zgadza się z liczbą paragonów z kasy fiskalnej lub raportem z terminala, co bardzo ułatwia zamykanie zmiany.
2. Karty podsumowań (Kafelki na górze ekranu)
Na górze zakładki Finanse znajdziesz kafelki z sumami:
- Łączny przychód – suma wszystkich opłaconych transakcji z wybranego okresu.
- Gotówka / Karta / Online / Portfel – rozbicie przychodów na konkretne metody płatności.
- Licznik transakcji przy każdej metodzie (np. "Gotówka: 15 transakcji") pokazuje, ile razy fizycznie przyjęto zapłatę tą metodą.
3. Płatności Mieszane (Gotówka + Karta)
Jeśli przyjmiesz od klienta płatność "mieszaną" (np. za zajęcia warte 100 zł klient daje 50 zł w gotówce, a resztę dopłaca kartą na terminalu):
- System w finansach rozbije tę transakcję poprawnie.
- Kwota 50 zł zasili kafelek podsumowujący "Gotówkę", a 50 zł kafelek "Karta".
- Gdy przefiltrujesz listę tylko dla transakcji gotówkowych, wpłata mieszana pojawi się tam, ale z uwzględnieniem tylko jej gotówkowej części.
4. Podział przychodów na kategorie
Oprócz podziału na metody płatności, przychody dzielone są na kategorie sprzedaży (wynajem kortów, lekcje indywidualne/grupowe, półkolonie, gastronomia, vouchery itd.). Kafelek „Przychody wg kategorii” oraz filtr „Kategorie przychodów” pozwalają sprawdzić, za co wpłynęły pieniądze. Szczegóły i tabelę warunków opisano w rozdziale Kategorie przychodów.
🛠️ Dokumentacja techniczna
Poniższa sekcja wyjaśnia mechanikę agregacji transakcji na poziomie kodu (in-memory grouping) dla deweloperów.
Architektura i algorytm grupowania
Dane o płatnościach są pobierane z tabeli payment. W celu unifikacji wierszy w jedną transakcję bez utraty danych pobocznych (np. zniżek), grupowanie odbywa się w pamięci przy użyciu funkcji pomocniczej groupAndMergePayments w pliku lib/actions/finances.ts.
Klucze Grupowania (Grouping Keys)
Rekordy płatności przypisywane są do grup na podstawie kryteriów (według priorytetów):
- Online (Session ID): Płatności z tym samym niepustym
session_id(zintegrowane z bramką Przelewy24). - Kasa fiskalna (Receipt ID): Płatności z tym samym niepustym
receipt_id. - Fakturownia (Invoice ID): Płatności z tym samym niepustym
invoice_id. - Płatności bezpośrednie w klubie: Płatności posiadające identyczny
paid_at(znacznik czasu, z dokładnością co do sekundy), tę samą metodę płatności oraz status (np. zbiorcze rozliczenie gotówkowe na recepcji). - Pozostałe: Każda płatność oczekująca, lub niemająca powyższych identyfikatorów, jest renderowana jako osobna transakcja.
Agregacja Wierszy (Row Merging)
Gdy rekordy trafiają do jednej grupy, ich pola są łączone:
amount: Suma wartości wszystkich płatności w grupie.playerName: Połączona unikalna lista graczy (rozdzielona przecinkami).activityType: Połączona lista typów aktywności.description: Otrzymuje sufiks(x[liczba_wierszy])jeśli opisy są spójne, w przeciwnym razie jest listą opartą o przecinki.- Karty benefitowe: Sumowanie identyfikatorów zniżek z kart typu Multisport/Medicover.
- Płatności mieszane: Obiekt rozbija się na
mixedPaymentCashAmountorazmixedPaymentCardAmount.
Flow w API / Server Actions
getFinancialTransactions:- Wyciąga pełną pulę rekordów pasującą do filtrów dat/użytkowników.
- Puszcza je przez
groupAndMergePayments. - Dołącza ewentualne transakcje ze sklepu (
Sale). - Sortuje czasowo, a na samym końcu nakłada paginację na poziomie tablicy w pamięci (offset, limit).
getFinancialSummary:- Strona
/dashboard/financespobiera pełną pulę transakcji raz i przekazuje ją tu jakopreloadedTransactions, dzięki czemu podsumowanie nie odpytuje bazy ponownie o te same rekordy. - Zapytania o karty benefitowe i rozliczenia
linked_paymentsą wykonywane jednymdb.batch([...])zamiast trzech osobnych round-tripów. - Iteruje i uzupełnia liczniki (agregaty gotówkowe, prowizje itd.) prezentowane w kafelkach UI.
- Strona
Odporność na przeciążenie bazy (D1)
Zapytania do D1 na ścieżkach renderowania stron finansów i płatności są opakowane w withD1Retry (lib/d1-retry.ts): przejściowe błędy typu D1 DB is overloaded. Too many requests queued. są ponawiane do 3 razy z rosnącym opóźnieniem i losowym jitterem, zamiast natychmiast wywracać render strony.