89 lines
6.5 KiB
Markdown
89 lines
6.5 KiB
Markdown
---
|
||
plan_id: 20260706-1430-modul-inwestycji
|
||
title: Moduł inwestycji — instrumenty, wpłaty/wypłaty, ręczne wyceny, pulpit
|
||
completed: 2026-07-06T14:55:00+02:00
|
||
storage: plan-first
|
||
quality_radar: degraded
|
||
---
|
||
|
||
# Summary: Moduł inwestycji — instrumenty, wpłaty/wypłaty, ręczne wyceny, pulpit
|
||
|
||
## Objective
|
||
|
||
Dodać moduł inwestycji: płaska lista instrumentów (kategorie główne, np. Obligacje, ETF), operacje wpłat/wypłat per instrument, ręczne snapshoty wyceny per instrument oraz pulpit inwestycji z wykresem zbiorczym w czasie i tabelą per instrument. W trakcie sesji dodano też pulpit globalny (`/dashboard`) i przepięto dotychczasowy pulpit finansów pod `/finances`.
|
||
|
||
## What Was Built
|
||
|
||
| Area | Result |
|
||
|------|--------|
|
||
| Schemat DB | 3 migracje `inv_instruments`, `inv_operations` (FK RESTRICT), `inv_valuations` (FK RESTRICT); seeder Obligacje/ETF |
|
||
| Modele | `InstrumentModel` (`withStats`, `portfolioTimeline`, `hasChildren` — logika zarobku netto w jednym miejscu), `InvOperationModel`, `ValuationModel` |
|
||
| CRUD | Instrumenty, operacje inwestycyjne (wpłaty/wypłaty), wyceny — pełny CRUD, filtry, blokada usunięcia instrumentu z powiązaniami |
|
||
| Pulpit inwestycji | `/investments`: kafelki (netto/wartość/zarobek), wykres liniowy 3-seryjny w czasie, tabela per instrument z % zwrotu |
|
||
| Pulpit globalny | `/dashboard`: kafel „Majątek razem" (saldo bieżące + wartość inwestycji) + sekcje Finanse/Inwestycje z linkami |
|
||
| Pulpit finansów | dotychczasowy dashboard przepięty pod `/finances` (`Dashboard::finances`) |
|
||
| Nawigacja | top-level „Pulpit" + dropdown „Finanse bieżące" (Pulpit finansów/Operacje/Kategorie) + dropdown „Inwestycje" (Pulpit/Wpłaty-wypłaty/Wyceny/Instrumenty) |
|
||
|
||
## Files Modified
|
||
|
||
- `app/Database/Migrations/2026-07-06-140001_CreateInvInstruments.php`, `...140002_CreateInvOperations.php`, `...140003_CreateInvValuations.php` — schemat inwestycji
|
||
- `app/Database/Seeds/DefaultInstrumentsSeeder.php` — idempotentny seed Obligacje/ETF
|
||
- `app/Models/InstrumentModel.php`, `InvOperationModel.php`, `ValuationModel.php` — domena inwestycji
|
||
- `app/Controllers/Instruments.php`, `InvOperations.php`, `Valuations.php`, `Investments.php` — CRUD + pulpit inwestycji
|
||
- `app/Controllers/Dashboard.php` — `index()` globalny + `finances()`
|
||
- `app/Views/instruments/{index,form}.php`, `inv_operations/{index,form}.php`, `valuations/{index,form}.php`, `investments/index.php` — widoki inwestycji
|
||
- `app/Views/dashboard/index.php` (globalny, przepisany), `app/Views/dashboard/finances.php` (przeniesiony finansowy)
|
||
- `app/Config/Routes.php` — trasy `investments/*`, `instruments/*`, `finances`
|
||
- `app/Views/layout/main.php` — nawigacja zgrupowana w dropdowny
|
||
|
||
## Acceptance Criteria Results
|
||
|
||
| Criterion | Status | Evidence |
|
||
|-----------|--------|----------|
|
||
| AC-1: instrumenty CRUD + blokada usunięcia | Pass | curl: dodanie OK; usunięcie ETF z operacjami → 302 + „Nie można usunąć instrumentu z operacjami lub wycenami" |
|
||
| AC-2: operacje wpłata/wypłata + filtry | Pass | curl: deposit/withdraw zapisane; filtr `type=withdraw` zwraca wiersz 200,00; `instrument_id=1` → brak |
|
||
| AC-3: ręczne wyceny per instrument | Pass | curl: wycena 950 na 2026-07-01 zapisana, użyta do zarobku |
|
||
| AC-4: zarobek netto | Pass | ETF: netto 800,00 (1000−200), zarobek 150,00 (950−800), 18,75% |
|
||
| AC-5: pulpit inwestycji | Pass | kafelki 800/950/150; `timeline=[{date:2026-07-01,net:800,value:950,profit:150}]`; tabela per instrument |
|
||
|
||
## Verification Results
|
||
|
||
| Check | Result | Notes |
|
||
|-------|--------|-------|
|
||
| `php spark migrate` | Pass | 3 tabele `inv_*` na bazie hostido |
|
||
| `php spark db:seed DefaultInstrumentsSeeder` | Pass | Obligacje, ETF (idempotentnie) |
|
||
| `php -l` (7 nowych plików PHP + Dashboard) | Pass | brak błędów składni |
|
||
| `php spark serve` + curl (login/CRUD/filtry/blokada/pulpity) | Pass | pełny przepływ end-to-end |
|
||
| Zarobek netto ETF = 150 (18,75%) | Pass | zgodne z ręcznym wyliczeniem |
|
||
| `/dashboard` globalny + `/finances` | Pass | globalny: majątek + sekcje; finances: 200 + 3 wykresy |
|
||
| Dane testowe | Cleaned | `inv_operations=0`, `inv_valuations=0`, seed instrumentów zachowany |
|
||
|
||
## Quality Radar Results
|
||
|
||
**Status:** degraded
|
||
|
||
- New risks: brak nowych ryzyk duplikacji (jscpd/ast-grep wyłączone polityką). Kopiowanie wzorców zapytań z `OperationModel` świadome — osobna domena.
|
||
- Resolved risks: logika zarobku netto w jednym miejscu (`InstrumentModel::withStats`), nie powielana w widokach; typ operacji `deposit|withdraw` jako ENUM + walidacja `in_list`.
|
||
- Deferred risks: pełna indeksacja `codebase-memory-mcp` odłożona do `$paul-map-codebase`; weryfikacja runtime.
|
||
- Raw outputs: `.paul/codebase/tooling_status.md`
|
||
|
||
## Deviations
|
||
|
||
- **Wykonanie inline zamiast `delegation: auto`** — 3 zadania ściśle sekwencyjne, wspólne pliki (`Routes.php`, modele); delegacja tylko powielałaby odczyty wzorców.
|
||
- **`.env` toggle** — tymczasowo `production→development` na czas migracji/testów (lokalny MySQL zgaszony, dev łączy do zdalnej hostido), po weryfikacji przywrócony na `production`. Netto zero zmian, boundary `.env` zachowany.
|
||
- **Nawigacja rozszerzona** — zamiast jednego linku „Inwestycje" powstały dwa dropdowny (na prośbę użytkownika o zgrupowanie wcześniejszych pozycji).
|
||
- **Pulpit globalny + `/finances`** — poza pierwotnym zakresem planu; dodane na prośbę użytkownika (globalny `/dashboard`, finansowy przepięty pod `/finances`).
|
||
|
||
## Key Decisions / Patterns
|
||
|
||
- **Jedno źródło prawdy dla zarobku**: `InstrumentModel::withStats` liczy `net_invested = Σwpłat − Σwypłat`, `profit = ostatnia_wycena − net_invested`; kontrolery/widoki tylko konsumują.
|
||
- **FK RESTRICT** na `inv_operations`/`inv_valuations` — instrument z powiązaniami nie da się skasować (spójne z blokadą w kontrolerze).
|
||
- **Szereg czasowy portfela** liczony w PHP (`portfolioTimeline`) z kilku prostych zapytań — bez okien SQL; trywialne przy ręcznych wycenach.
|
||
- **Pulpit globalny** agreguje majątek = saldo bieżące + wartość inwestycji; szczegóły delegowane do `/finances` i `/investments`.
|
||
|
||
## Follow-up
|
||
|
||
- Wdrożenie produkcyjne `https://finanse.projectpro.pl/` — wgrać pliki + `vendor/`, uruchomić `php spark migrate` na serwerze (3 nowe tabele `inv_*`); `CI_ENVIRONMENT=production`. Schemat finansów bez zmian.
|
||
- Opcjonalnie: `$paul-map-codebase` (pełny indeks codebase-memory-mcp) przed kolejnym planem.
|
||
- Możliwe rozszerzenia: wykres per instrument, historia wartości vs wpłat na osi czasu z interpolacją, eksport.
|