Files
2026-07-06 20:16:00 +02:00

89 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 (1000200), zarobek 150,00 (950800), 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.