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>
326 lines
16 KiB
Markdown
326 lines
16 KiB
Markdown
# 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** să văd indicatorii de lichiditate calculați automat
|
||
**Pentru că** vreau să ș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** să văd indicatorii de eficiență (DSO, DPO, rate)
|
||
**Pentru că** vreau să ș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** să văd indicatorii de risc și aging creanțe/datorii
|
||
**Pentru că** vreau să ș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** să văd indicatorii de cash flow
|
||
**Pentru că** vreau să ș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** să văd evoluția vânzărilor și achizițiilor
|
||
**Pentru că** vreau să ș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** să văd scorul Altman Z-Score calculat automat
|
||
**Pentru că** vreau să ș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 să 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** să văd evoluția fiecărui indicator pe 12 luni
|
||
**Pentru că** vreau să î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 să 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 să aibă o mini-diagramă de evoluție
|
||
**Pentru că** vreau să 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** să 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** să 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** să 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** să 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 să 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 să 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 să 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 să 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 să 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 să 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 să fie configurabile per firmă sau fixe? → Fixe pentru MVP
|