# 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