feat(financial-indicators): Complete Financial Indicators Dashboard Card

Implementare completă a card-ului Indicatori Financiari în Dashboard Solduri:

Backend:
- Model FinancialIndicators cu 22+ indicatori organizați pe categorii
- Service cu calcule din VBAL (Lichiditate, Eficiență, Risc, Cash Flow, Dinamică)
- Altman Z-Score cu toate componentele (X1-X4) și valori absolute
- Profitabilitate cu ROA, ROE, Cifra Afaceri, Cheltuieli separate (operaționale/financiare)
- Caching inteligent pe company_id, luna, an

Frontend:
- FinancialIndicatorsCard.vue cu 4 indicatori principali collapsed
- Expanded view grupat pe categorii (desktop + mobile BottomSheet)
- Subindicatori pentru verificare manuală în balanță
- Traduceri complete în română
- Dark mode support complet
- Sparklines cu tooltips
- Responsive design (desktop grid + mobile carousel)

Documentație:
- PRD complet cu specificații și formule
- Descrieri cu conturi din planul contabil român (OMFP 1802/2014)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-01-20 17:32:48 +00:00
parent 15327687f4
commit dd4b90f922
14 changed files with 6800 additions and 237 deletions

View File

@@ -0,0 +1,325 @@
# PRD: Card Indicatori Financiari în Dashboard Solduri
## 1. Introducere
Adăugarea unui card nou în dashboard-ul solduri cu indicatori financiari esențiali pentru evaluare bancară/creditare și analiză sănătate financiară a firmei. Indicatorii vor include rate de lichiditate, eficiență, risc, și scorul Altman Z-Score pentru predicția falimentului - aceiași indicatori pe care îi folosesc băncile și evaluatorii pentru acordarea de credite.
## 2. Obiective
### Obiectiv Principal
- Oferirea unei viziuni complete asupra sănătății financiare a firmei într-un singur card, cu indicatori calculați automat din datele contabile
### Obiective Secundare
- Vizualizarea evoluției indicatorilor pe 12 luni (sparklines)
- Comparație Year-over-Year pentru fiecare indicator
- Alertare vizuală (cod culoare) pentru valori în afara pragurilor recomandate
- Calculul scorului Altman Z-Score pentru evaluarea riscului de faliment
### Metrici de Succes
- Toți cei 22+ indicatori sunt calculați corect și afișați
- Sparklines afișează evoluția corectă pe 12 luni
- Cod culoare (verde/galben/roșu) corespunde pragurilor standard
- Timpul de încărcare < 2 secunde (cu cache)
## 3. User Stories
### US-001: Backend - Serviciu Agregare Conturi Balanță
**Ca** dezvoltator backend
**Vreau** un serviciu care agregă soldurile din balanța de verificare (VBAL) pe clase de conturi
**Pentru că** am nevoie de date agregate pentru calculul indicatorilor de bilanț și Altman Z-Score
**Acceptance Criteria:**
- [ ] Creat `backend/modules/reports/services/financial_indicators_service.py`
- [ ] Metoda `get_balance_sheet_aggregates()` returnează solduri agregate pentru: active_imobilizate, stocuri, creante, disponibilitati, capital_propriu, rezultat, datorii_termen_lung, datorii_curente, venituri, cheltuieli_operationale
- [ ] Query-ul folosește VBAL view cu LIKE pentru prefixe conturi (ex: `cont LIKE '20%'`)
- [ ] Cache implementat cu TTL 30 minute
- [ ] Unit test verifică structura răspunsului
### US-002: Backend - Calcul Indicatori Lichiditate
**Ca** utilizator al dashboard-ului
**Vreau** văd indicatorii de lichiditate calculați automat
**Pentru că** vreau știu dacă firma poate plăti datoriile pe termen scurt
**Acceptance Criteria:**
- [ ] Calculat `lichiditate_curenta` = Active Curente / Datorii Curente
- [ ] Calculat `lichiditate_imediata` (Quick Ratio) = (Trezorerie + Creanțe) / Datorii Curente
- [ ] Calculat `lichiditate_vedere` (Cash Ratio) = Trezorerie / Datorii Curente
- [ ] Fiecare indicator include: valoare, status (good/warning/danger), prag_min, prag_max
- [ ] npm run typecheck passes
### US-003: Backend - Calcul Indicatori Eficiență
**Ca** utilizator al dashboard-ului
**Vreau** văd indicatorii de eficiență (DSO, DPO, rate)
**Pentru că** vreau știu cât de repede convertesc resursele în bani
**Acceptance Criteria:**
- [ ] Calculat `dso` (Durata Încasare) = (Sold Clienți / Facturări Lunare) × 30 zile
- [ ] Calculat `dpo` (Durata Plată) = (Sold Furnizori / Achiziții Lunare) × 30 zile
- [ ] Calculat `cash_conversion_cycle` = DSO - DPO
- [ ] Calculat `rata_incasare` = Încasări / Facturări × 100
- [ ] Calculat `rata_plata` = Plăți / Achiziții × 100
- [ ] npm run typecheck passes
### US-004: Backend - Calcul Indicatori Risc și Aging
**Ca** utilizator al dashboard-ului
**Vreau** văd indicatorii de risc și aging creanțe/datorii
**Pentru că** vreau știu cât de sănătos este portofoliul de creanțe
**Acceptance Criteria:**
- [ ] Calculat `creante_restante_pct` = Creanțe Restante / Creanțe Total × 100
- [ ] Calculat `creante_90plus_pct` = Creanțe 90+ zile / Creanțe Total × 100
- [ ] Calculat `datorii_restante_pct` = Datorii Restante / Datorii Total × 100
- [ ] Calculat `raport_datorii_trezorerie` = Datorii Furnizori / Trezorerie
- [ ] npm run typecheck passes
### US-005: Backend - Calcul Indicatori Cash Flow
**Ca** utilizator al dashboard-ului
**Vreau** văd indicatorii de cash flow
**Pentru că** vreau știu dacă firma generează sau consumă numerar
**Acceptance Criteria:**
- [ ] Calculat `flux_net_lunar` = Încasări - Plăți (luna curentă)
- [ ] Calculat `cash_flow_ytd` = Suma fluxurilor de la ianuarie
- [ ] Calculat `flux_net_yoy_pct` = (CF_curent - CF_anterior) / CF_anterior × 100
- [ ] Calculat `acoperire_cash_flow` = Cash Flow / Datorii Restante
- [ ] npm run typecheck passes
### US-006: Backend - Calcul Indicatori Dinamică
**Ca** utilizator al dashboard-ului
**Vreau** văd evoluția vânzărilor și achizițiilor
**Pentru că** vreau știu dacă afacerea crește sau scade
**Acceptance Criteria:**
- [ ] Calculat `crestere_vanzari_yoy` = (Vânzări_curent - Vânzări_anterior) / Vânzări_anterior × 100
- [ ] Calculat `crestere_achizitii_yoy` = similar
- [ ] Calculat `marja_implicita` = (Vânzări - Achiziții) / Vânzări × 100
- [ ] npm run typecheck passes
### US-007: Backend - Calcul Altman Z-Score
**Ca** utilizator al dashboard-ului
**Vreau** văd scorul Altman Z-Score calculat automat
**Pentru că** vreau știu riscul de faliment al firmei conform standardelor internaționale
**Acceptance Criteria:**
- [ ] Calculat X1 = Working Capital / Total Assets
- [ ] Calculat X2 = Retained Earnings (cont 117) / Total Assets
- [ ] Calculat X3 = EBIT (Cl.7 - Cl.6 fără 66x) / Total Assets
- [ ] Calculat X4 = Equity (Cl.1 capital) / Total Liabilities
- [ ] Calculat Z'' = 6.56×X1 + 3.26×X2 + 6.72×X3 + 1.05×X4
- [ ] Status: "Zonă Sigură" (>2.60), "Zonă Gri" (1.10-2.60), "Zonă Risc" (<1.10)
- [ ] Răspunsul include și componentele individuale (X1-X4) pentru transparență
- [ ] npm run typecheck passes
### US-008: Backend - Endpoint API Financial Indicators
**Ca** frontend developer
**Vreau** un endpoint API care returnează toți indicatorii calculați
**Pentru că** am nevoie afișez datele în UI
**Acceptance Criteria:**
- [ ] Endpoint `GET /api/reports/dashboard/financial-indicators`
- [ ] Parametri: company (required), luna (optional), an (optional)
- [ ] Răspuns JSON cu structura: { lichiditate: {...}, eficienta: {...}, risc: {...}, cash_flow: {...}, dinamica: {...}, altman_zscore: {...} }
- [ ] Fiecare indicator include: value, status, threshold_min, threshold_max, sparkline_data (array 12 valori)
- [ ] Cache 30 minute implementat
- [ ] Response time < 500ms (cu cache)
- [ ] npm run typecheck passes
### US-009: Backend - Date Istorice pentru Sparklines
**Ca** utilizator
**Vreau** văd evoluția fiecărui indicator pe 12 luni
**Pentru că** vreau înțeleg trendul, nu doar valoarea curentă
**Acceptance Criteria:**
- [ ] Fiecare indicator include câmp `sparkline_data` cu array de 12 valori (ultimele 12 luni)
- [ ] Include și `sparkline_labels` cu etichetele lunilor (ex: ["Feb 24", "Mar 24", ...])
- [ ] Datele sunt calculate pentru fiecare lună din ultimele 12
- [ ] npm run typecheck passes
### US-010: Frontend - Component FinancialIndicatorsCard
**Ca** utilizator al dashboard-ului
**Vreau** un card vizual care afișează indicatorii financiari
**Pentru că** vreau văd rapid starea financiară a firmei
**Acceptance Criteria:**
- [ ] Creat `src/modules/reports/components/dashboard/cards/FinancialIndicatorsCard.vue`
- [ ] Header cu titlu "Indicatori Financiari" și selector perioadă
- [ ] Tabs pentru categorii: Lichiditate, Eficiență, Risc, Z-Score
- [ ] Grid 2x2 sau 2x3 pentru indicatori în fiecare tab
- [ ] Folosește design tokens din `docs/DESIGN_TOKENS.md`
- [ ] npm run typecheck passes
- [ ] Verify in browser that card-ul se afișează corect
### US-011: Frontend - Component IndicatorItem cu Sparkline
**Ca** utilizator
**Vreau** fiecare indicator aibă o mini-diagramă de evoluție
**Pentru că** vreau văd trendul vizual
**Acceptance Criteria:**
- [ ] Creat sub-component pentru afișarea unui indicator individual
- [ ] Afișează: nume, valoare curentă, status (icon + culoare), sparkline
- [ ] Cod culoare: verde (good), galben (warning), roșu (danger)
- [ ] Sparkline folosește array-ul de 12 valori
- [ ] Hover pe sparkline arată valoarea lunii
- [ ] npm run typecheck passes
- [ ] Verify in browser that sparkline-urile se afișează corect
### US-012: Frontend - Expand pentru Detalii Complete
**Ca** utilizator
**Vreau** pot expanda cardul pentru a vedea toți indicatorii
**Pentru că** unii indicatori sunt mai puțin importanți dar vreau acces la ei
**Acceptance Criteria:**
- [ ] Buton/chevron pentru expand/collapse
- [ ] Starea collapsed arată 4-6 indicatori principali
- [ ] Starea expanded arată toți 22+ indicatori în format tabel
- [ ] Animație smooth la expand/collapse
- [ ] npm run typecheck passes
- [ ] Verify in browser that expand/collapse funcționează
### US-013: Frontend - Store Integration
**Ca** frontend developer
**Vreau** integrez datele în Pinia store
**Pentru că** am nevoie de state management pentru indicatori
**Acceptance Criteria:**
- [ ] Adăugat metodă `loadFinancialIndicators(companyId, luna, an)` în `dashboard.js` store
- [ ] State pentru `financialIndicators` cu loading, error, data
- [ ] Computed properties pentru fiecare categorie de indicatori
- [ ] Reîncărcare automată când se schimbă compania sau perioada
- [ ] npm run typecheck passes
### US-014: Frontend - Integrare în DashboardView Desktop
**Ca** utilizator pe desktop
**Vreau** văd cardul de indicatori în dashboard
**Pentru că** vreau acces rapid la informații
**Acceptance Criteria:**
- [ ] Import `FinancialIndicatorsCard` în `DashboardView.vue`
- [ ] Adăugat în grid-ul desktop (rând nou sub metric cards)
- [ ] Card ocupă full width sau 2 coloane
- [ ] Se încarcă împreună cu restul dashboard-ului
- [ ] npm run typecheck passes
- [ ] Verify in browser (desktop) that cardul apare corect în layout
### US-015: Frontend - Integrare în DashboardView Mobile
**Ca** utilizator pe mobil
**Vreau** văd cardul de indicatori în carusel
**Pentru că** vreau acces la informații și pe telefon
**Acceptance Criteria:**
- [ ] Adăugat pagină nouă (Page 6) în `SwipeableCards` carousel
- [ ] Layout adaptat pentru ecran mic (1 coloană sau 2x2 mai mic)
- [ ] Touch-friendly (tap pentru expand, swipe pentru navigare)
- [ ] Respectă padding pentru MobileTopBar și MobileBottomNav
- [ ] npm run typecheck passes
- [ ] Verify in browser (mobile viewport) that cardul funcționează corect
### US-016: Frontend - Dark Mode Support
**Ca** utilizator
**Vreau** cardul arate bine în dark mode
**Pentru că** folosesc aplicația și seara
**Acceptance Criteria:**
- [ ] Culorile de status funcționează în ambele teme
- [ ] Sparklines au contrast suficient
- [ ] Textul e lizibil în dark mode
- [ ] Folosește variabile CSS pentru culori (nu hardcodate)
- [ ] npm run typecheck passes
- [ ] Verify in browser (dark mode) that totul e vizibil și lizibil
## 4. Cerințe Funcționale
1. [REQ-001] Sistemul trebuie calculeze toți cei 22 indicatori financiari definiți
2. [REQ-002] Utilizatorul poate vedea valoarea curentă și evoluția pe 12 luni pentru fiecare indicator
3. [REQ-003] Sistemul trebuie afișeze cod culoare pentru status (verde/galben/roșu) bazat pe praguri standard
4. [REQ-004] Când se schimbă compania sau perioada, indicatorii se recalculează automat
5. [REQ-005] Altman Z-Score trebuie calculat conform formulei Z'' pentru firme private non-manufacturiere
6. [REQ-006] Sistemul trebuie cacheze rezultatele pentru 30 minute
7. [REQ-007] Datele se încarcă în paralel cu restul dashboard-ului (nu secvențial)
## 5. Non-Goals (Ce NU facem)
- **NU** implementăm export PDF/Excel al indicatorilor (poate fi adăugat ulterior)
- **NU** implementăm alerte email când indicatorii depășesc praguri
- **NU** implementăm comparație între multiple firme
- **NU** implementăm indicatori care necesită date care nu sunt în sistemul contabil (ex: prețul acțiunilor pentru Z-Score original)
- **NU** modificăm indicatorii existenți din cardurile solduri (Trezorerie, Clienți, Furnizori, TVA)
## 6. Considerații Tehnice
### Stack/Tehnologii
- **Backend**: Python, FastAPI, python-oracledb, Pydantic
- **Frontend**: Vue.js 3, Pinia, PrimeVue, CSS Variables
- **Database**: Oracle (view VBAL pentru balanță)
### Patterns de Urmat
- Backend service pattern cu `@cached` decorator (vezi `dashboard_service.py`)
- Frontend component pattern cu props pentru configurare (vezi `SolduriCompactCard.vue`)
- CSS design tokens (vezi `docs/DESIGN_TOKENS.md`)
### Conturi VBAL Necesare
```python
ACCOUNT_GROUPS = {
'active_imobilizate': ['20%', '21%', '22%', '23%', '24%', '25%', '26%', '27%', '28%'],
'stocuri': ['30%', '31%', '32%', '33%', '34%', '35%', '36%', '37%', '38%', '39%'],
'creante': ['41%', '44%', '45%', '46%', '47%'],
'disponibilitati': ['51%', '53%'],
'capital_propriu': ['101', '102', '103', '104', '105', '106', '107', '108', '109'],
'rezultat': ['117', '121', '129'],
'datorii_termen_lung': ['161', '162', '163', '164', '165', '166', '167', '168', '169'],
'datorii_curente': ['401', '403', '404', '405', '408', '419', '421', '423', '424', ...],
'venituri': ['70%', '71%', '72%', '74%', '75%', '78%'],
'cheltuieli_operationale': ['60%', '61%', '62%', '63%', '64%', '65%', '68%'],
}
```
### Dependențe
- Depinde de endpoint-urile existente `/dashboard/summary` și `/dashboard/trends`
- Depinde de view-ul Oracle VBAL din schema companiei
### Riscuri Tehnice
- **R1**: Unele firme pot nu aibă toate conturile populate (soluție: returnăm null/N/A pentru indicatorii care nu pot fi calculați)
- **R2**: Query-ul VBAL cu multe LIKE poate fi lent (soluție: cache agresiv 30min)
- **R3**: Valorile Z-Score pot fi distorsionate pentru firme foarte mici (soluție: afișăm disclaimer)
## 7. Considerații UI/UX
### Layout Card (Desktop)
```
┌─────────────────────────────────────────────────────────────────┐
│ 📊 INDICATORI FINANCIARI Ianuarie 2025 ▼ │
├──────────────┬──────────────┬──────────────┬───────────────────┤
│ LICHIDITATE │ EFICIENȚĂ │ RISC │ ALTMAN Z │
├──────────────┴──────────────┴──────────────┴───────────────────┤
│ Quick Ratio DSO Creanțe Rest. Z-Score │
│ 1.85x 32 zile 15.2% 2.45 │
│ ✅ >1.0 ⚠️ <45 ✅ <20% ⚠️ Zonă Gri │
│ ▁▂▃▄▅▆▇█▇▆▅ ▇▆▅▄▃▂▁▂▃▄▅▆ ▁▁▂▂▃▃▄▄▅▅▆▆ ▃▄▄▅▅▆▆▇▇███ │
├─────────────────────────────────────────────────────────────────┤
│ ▼ Mai multe indicatori Refresh ↻ │
└─────────────────────────────────────────────────────────────────┘
```
### Stări UI
- **Loading**: Skeleton/shimmer pentru card
- **Error**: Mesaj de eroare cu buton retry
- **Empty**: "Datele nu sunt disponibile pentru această perioadă"
- **Success**: Afișare indicatori cu cod culoare
### Cod Culoare Status
- 🟢 **Verde** (--green-600): Valoare în zona optimă
- 🟡 **Galben** (--yellow-600): Valoare acceptabilă, de urmărit
- 🔴 **Roșu** (--red-600): Valoare critică, necesită atenție
## 8. Success Metrics
- **Completitudine**: 22/22 indicatori calculați și afișați
- **Performanță**: Response time API < 500ms (cached)
- **UX**: Card încărcat complet în < 2 secunde
- **Acuratețe**: Z-Score calculat corect conform formula standard
## 9. Open Questions
- [x] Care indicatori fie vizibili implicit vs la expand? 4-6 principali vizibili, restul la expand
- [x] Vrem tab-uri sau scroll vertical pentru categorii? Tabs pentru categorii
- [ ] Pragurile pentru cod culoare fie configurabile per firmă sau fixe? Fixe pentru MVP