Model danych
Cały stan planu to jeden spójny obiekt (w trybie chmurowym przechowywany jako
jsonb na gospodarstwo). Najważniejsze elementy:
Pozycje portfela
Inwestycje i dług (kredyt). Każda pozycja ma m.in.: wartość bieżącą, wpłatę
docelową, stopę (oprocentowanie/zwrot), cel, ratę/okres/datę wykupu oraz
kategorię (categoryId).
Opcjonalnie: typ konta (accountKind — IKE/IKZE/PPK/PPE/OIPE/zwykłe/bank,
wrapper podatkowy), instrument (instrumentType — ETF/akcje/obligacje/…),
znacznik JDG (wyższy limit IKZE), ticker/ISIN/alokacja docelowa, właściciel
i beneficjent. Pola są wstecznie kompatybilne — brak typu konta = zachowanie jak
dotąd.
Aktywa poza portfelem
Nieruchomości, działki, gotówka, pojazdy — wartość i opcjonalna stopa wzrostu.
Każde aktywo ma klasę (assetClass): cash (gotówka/oszczędności),
real_estate (nieruchomości; realEstateUsage: główne/wynajem/działka) lub
physical_asset (rzeczowe: physicalKind auto/sprzęt/kolekcja). Brak klasy →
wnioskowana (gotówka po nazwie, inaczej nieruchomość), więc starsze dane działają
bez migracji. Flagi includeInInvestable / liquid sterują soczewkami majątku
(domyślne wg klasy), a growth opisuje zachowanie w projekcji (patrz
Jak liczymy).
Cele
Większe wydatki z kwotą, terminem i postępem odkładania. Opcjonalnie: powiązane źródło (id pozycji lub aktywa; nazwa zostaje też w polu tekstowym, czytelna dla starszych wersji aplikacji), znacznik „licz Odłożone ze źródła" oraz oznaczenie zrealizowany z datą. Profil planu zapisuje też, kto i kiedy zmienił wspólną miesięczną kwotę oszczędności.
Wpisy miesięczne
Per miesiąc: przychody (per osoba), wpłaty/nadpłaty z podziałem na osoby (suma trafia do obliczeń), budżet na oszczędności, raty kredytu, ocena kosztów życia, notatka, oznaczenie „kto z domowników zrobił przegląd" oraz ile już doliczono do wartości portfela (pozwala doliczać przyrostowo, bez podwójnego liczenia).
Od października 2026 wpis ma też wypłaty / sprzedaż z kont (withdrawals,
jedna kwota dla gospodarstwa) i konta zamknięte w tym miesiącu
(closedPositionIds). Tak jak przy wpłatach wpis pamięta, ile wypłat odjęto
już od wartości (appliedWithdrawals, dla kont walutowych także kwotę w
walucie), oraz wartość konta w chwili zamknięcia (appliedClosures). Dzięki
temu ponowny zapis niczego nie odejmuje dwa razy, a usunięcie wpisu albo
odznaczenie zamknięcia przywraca konto dokładnie takie, jakie było. Sprzedaż
jednostek (krypto, złoto, ETF z ilością) to automatyczna transakcja
auto-sell-RRRR-MM w historii pozycji.
Konta zamknięte leżą osobno (closedPositions, każde z closedMonth) —
poza listą pozycji, więc żadne bieżące obliczenie ich nie liczy; zostają dla
historii i „Przywróć". Przy synchronizacji pary o koncie obecnym po obu
stronach decyduje nowsza wersja (zamknięte na jednym urządzeniu nie wraca jako
aktywne z drugiego).
Konta i operacje
Od października 2026: konta (accounts — nazwa, instytucja, typ konta,
właściciel, id wolnych środków, miesiąc zamknięcia) i operacje
(operations — konto, data, rodzaj, instrument, sztuki, cena i waluta, kwota
w PLN, prowizja, kto wpłacił, czy wpłata/wypłata to przepływ czy przeniesienie).
Instrumenty konta to zwykłe pozycje z accountId; wolne środki — pozycja
gotówkowa z bazą (cashBase) na stan otwarcia i korekty. Ilość i koszt
instrumentu wynikają z transakcji init-* (stan otwarcia) i op-* (z operacji).
Przepływy (wpłaty/wypłaty) z operacji są przepisywane do wpisu miesiąca jako
kwoty na wolne środki konta.
Wolne środki w walutach: konto ma mapę fxCashIds (waluta → id pozycji), a
pozycja trzyma saldo w walucie (fxAmount, baza cashBase w walucie) i wartość
w PLN. Operacja z cashCurrency i cashAmount (kwota w walucie) zmienia tę
gotówkę zamiast złotówkowej. Kurs operacji to amount ÷ cashAmount. Przepływ
miesiąca trafia na id gotówki, która przyjęła pieniądze. Konto pamięta też
sumę wpisaną w kroku 3 (brokerValues, miesiąc → kwota w PLN). Przy synchronizacji pary konta i operacje łączą się
po id (operacje z obu urządzeń przetrwają), a salda i przepływy liczą się od
nowa z połączonego dziennika.
Kategorie
Grupowanie pozycji definiowane przez użytkownika (categories: Category[] w
stanie). Każda kategoria ma id, nazwę, kolor (z palety) i opcjonalne emoji;
kolejność na liście = kolejność wyświetlania. Domyślny zestaw to Emerytura,
Inwestycje, Kredyt, Obligacje, Oszczędności i Krypto — ale można je dowolnie
zmieniać, dodawać i usuwać (Ustawienia → Kategorie). Migracja ze starego modelu
„filarów" (stałe I–V) mapuje je na kategorie ze stałymi id (Bitcoin → Krypto),
bez utraty przypisań pozycji.
Do której kategorii trafia nowa pozycja
Szablon z katalogu i wiersz importu wskazują kategorię domyślną (np. Bitcoin →
crypto, obligacje ROS/EDO → obligacje, złoto i inne metale → inwestycje).
Twój plan może takiej kategorii nie mieć albo mieć własną o tym samym znaczeniu,
np. „Krypto" założoną ręcznie. Dlatego aplikacja szuka po kolei:
- kategorii o tym samym
id, - kategorii o tym samym znaczeniu: porównuje nazwę i
idbez wielkich liter i polskich znaków, ze słownikiem PL/EN/DE (np. krypto, crypto, kryptowaluty, bitcoin; obligacje, bonds, Anleihen; emerytura, retirement, Rente; oszczędności, savings; kredyt, hipoteka, loan), - gdy takiej nie ma — dodaje brakującą kategorię domyślną (nazwa w języku aplikacji, wolny kolor z palety) i wstawia do niej pozycję.
Do pierwszej kategorii z listy trafia tylko pozycja, której kategorii nie da się rozpoznać. Import z brokera wybiera kategorię według instrumentu: krypto → Krypto, obligacje detaliczne → Obligacje, konto i lokata → Oszczędności, ETF-y, akcje, fundusze i metale → Inwestycje.
Przy wczytaniu planu (z urządzenia, z kopii zapasowej i z chmury — po
odszyfrowaniu) pozycja z nieznanym id kategorii też najpierw szuka kategorii
o tym znaczeniu, potem kategorii wg instrumentu, a dopiero na końcu trafia do
pierwszej z listy.
Jednorazowa naprawa (schemat 9). Plany zapisane przed tą zmianą przechodzą przy pierwszym wczytaniu dwie poprawki:
- pozycje krypto (typ instrumentu „krypto") stojące w innej kategorii, np. w Inwestycjach, przechodzą do kategorii krypto planu — domyślnej albo Twojej własnej o tym znaczeniu. Inne pozycje zostają tam, gdzie były. Gdy plan nie ma kategorii krypto, nic się nie zmienia (przy wczytaniu kategorii nie tworzymy). Jeśli potem świadomie przeniesiesz Bitcoina z powrotem, zostanie tam, gdzie go postawisz — naprawa działa raz;
- kategoria domyślna
cryptoz dawną nazwą dokładnie „Crypto" dostaje dzisiejszą nazwę „Krypto" — tylko w planach z krajem Polska lub Niemcy. Nazwy nadanej przez Ciebie nie zmieniamy.
Naprawa nie dotyka danych finansowych: zmienia tylko przypisanie do kategorii (Pulpit, Wpis), więc wartość netto, FIRE i projekcje liczą się tak samo.
Profil i preferencje
- Profil planu (współdzielony w Duo): osoby (
members), kraj, główny cel. Każda osoba ma imię, emoji, datę urodzenia i — dorosły — znacznik JDG (wyższy limit IKZE). Starsze plany trzymały datę urodzenia tylko w profilu (profile.birthDate); dla osoby głównej czytamy ją stamtąd, gdy osoba nie ma własnej — bez migracji danych. Nowy zapis trafia do osoby. - Preferencje urządzenia (NIE synchronizowane): język, motyw, rola w planie.
Snapshoty wartości netto
Lekki zapis wartości netto per miesiąc — zasila trend majątku (30 dni / 12 mies.).
Każdy odczyt i zapis danych przechodzi przez walidację (Zod) — patrz Bezpieczeństwo.