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>
874 lines
34 KiB
Python
874 lines
34 KiB
Python
"""
|
|
Pydantic models pentru indicatori financiari.
|
|
|
|
Definește structurile de date pentru:
|
|
- BalanceSheetAggregates: Solduri agregate din balanța de verificare
|
|
- IndicatorResult: Rezultatul standardizat cu sparkline data pentru vizualizare trend
|
|
- Modele pentru indicatori de lichiditate, eficiență, risc și Altman Z-Score
|
|
"""
|
|
from decimal import Decimal
|
|
from typing import Optional, List
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class BalanceSheetAggregates(BaseModel):
|
|
"""
|
|
Solduri agregate din balanța de verificare (VBAL) pe categorii de conturi.
|
|
|
|
Agregă datele din VBAL folosind prefixe de conturi conform Planului de
|
|
Conturi General (PCG) românesc pentru calculul indicatorilor financiari.
|
|
|
|
Attributes:
|
|
company_id: ID-ul firmei
|
|
luna: Luna contabilă (1-12)
|
|
an: Anul contabil
|
|
active_imobilizate: Active imobilizate nete (brut - amortizări - ajustări)
|
|
stocuri: Valoarea stocurilor (brut - ajustări depreciere)
|
|
creante: Creanțe nete (brut - ajustări depreciere)
|
|
disponibilitati: Disponibilități bănești (bancă + casă)
|
|
capital_propriu: Capital social + prime + rezerve
|
|
rezultat: Rezultat reportat + rezultatul exercițiului curent
|
|
datorii_termen_lung: Datorii cu scadență > 1 an
|
|
datorii_curente: Datorii cu scadență <= 1 an
|
|
venituri: Venituri din exploatare (pentru calcul EBIT)
|
|
cheltuieli_operationale: Cheltuieli de exploatare (pentru calcul EBIT)
|
|
"""
|
|
company_id: int = Field(description="ID-ul firmei")
|
|
luna: int = Field(ge=1, le=12, description="Luna contabilă (1-12)")
|
|
an: int = Field(ge=2000, le=2100, description="Anul contabil")
|
|
|
|
# Active
|
|
active_imobilizate: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Active imobilizate nete (Clasa 2 - amortizări)"
|
|
)
|
|
stocuri: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Stocuri (Clasa 3 - ajustări depreciere)"
|
|
)
|
|
creante: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Creanțe comerciale și alte creanțe (4111, 461, etc.)"
|
|
)
|
|
disponibilitati: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Disponibilități (bancă 512x + casă 531x)"
|
|
)
|
|
|
|
# Pasive - Capitaluri
|
|
capital_propriu: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Capital social + prime + rezerve (101, 104, 105, 106)"
|
|
)
|
|
rezultat: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Rezultat reportat + rezultat curent (107, 117, 121)"
|
|
)
|
|
|
|
# Pasive - Datorii
|
|
datorii_termen_lung: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Datorii pe termen lung (Clasa 16)"
|
|
)
|
|
datorii_curente: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Datorii curente (401, 421, 4423, 462, etc.)"
|
|
)
|
|
|
|
# Venituri și Cheltuieli (pentru calcul EBIT în Altman Z-Score)
|
|
venituri: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Venituri din exploatare (Clasa 7)"
|
|
)
|
|
cheltuieli_operationale: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Cheltuieli operaționale (Clasa 6 fără 66x)"
|
|
)
|
|
cheltuieli_financiare: Decimal = Field(
|
|
default=Decimal('0'),
|
|
description="Cheltuieli financiare (Clasa 66 - dobânzi, diferențe curs)"
|
|
)
|
|
|
|
# Computed properties pentru calculele ulterioare
|
|
@property
|
|
def active_curente(self) -> Decimal:
|
|
"""Active curente = stocuri + creanțe + disponibilități"""
|
|
return self.stocuri + self.creante + self.disponibilitati
|
|
|
|
@property
|
|
def total_active(self) -> Decimal:
|
|
"""Total active = active imobilizate + active curente"""
|
|
return self.active_imobilizate + self.active_curente
|
|
|
|
@property
|
|
def total_datorii(self) -> Decimal:
|
|
"""Total datorii = datorii termen lung + datorii curente"""
|
|
return self.datorii_termen_lung + self.datorii_curente
|
|
|
|
@property
|
|
def capitaluri_proprii(self) -> Decimal:
|
|
"""Capitaluri proprii = capital propriu + rezultat"""
|
|
return self.capital_propriu + self.rezultat
|
|
|
|
@property
|
|
def ebit(self) -> Decimal:
|
|
"""EBIT (Earnings Before Interest and Taxes) = venituri - cheltuieli operaționale"""
|
|
return self.venituri - self.cheltuieli_operationale
|
|
|
|
@property
|
|
def working_capital(self) -> Decimal:
|
|
"""Working capital (fond de rulment) = active curente - datorii curente"""
|
|
return self.active_curente - self.datorii_curente
|
|
|
|
class Config:
|
|
"""Configurare Pydantic"""
|
|
from_attributes = True
|
|
json_schema_extra = {
|
|
"example": {
|
|
"company_id": 123,
|
|
"luna": 12,
|
|
"an": 2024,
|
|
"active_imobilizate": 1500000.00,
|
|
"stocuri": 350000.00,
|
|
"creante": 420000.00,
|
|
"disponibilitati": 180000.00,
|
|
"capital_propriu": 800000.00,
|
|
"rezultat": 250000.00,
|
|
"datorii_termen_lung": 500000.00,
|
|
"datorii_curente": 400000.00,
|
|
"venituri": 2500000.00,
|
|
"cheltuieli_operationale": 2100000.00
|
|
}
|
|
}
|
|
|
|
|
|
class IndicatorResult(BaseModel):
|
|
"""
|
|
Rezultatul standardizat pentru un indicator financiar.
|
|
|
|
Fiecare indicator returnează valoarea calculată împreună cu
|
|
statusul (good/warning/danger), pragurile de referință și
|
|
date pentru sparkline (evoluția pe ultimele 12 luni).
|
|
|
|
Attributes:
|
|
value: Valoarea calculată a indicatorului (None dacă nu se poate calcula)
|
|
status: Statusul indicatorului - 'good', 'warning', sau 'danger'
|
|
threshold_min: Pragul minim pentru status 'good'
|
|
threshold_max: Pragul maxim pentru status 'good' (opțional)
|
|
message: Mesaj explicativ (opțional, pentru cazuri speciale)
|
|
sparkline_data: Array cu valorile indicatorului pe ultimele 12 luni (pentru vizualizare trend)
|
|
sparkline_labels: Array cu etichetele lunilor în format 'MMM YY' (ex: 'Feb 24', 'Mar 24')
|
|
"""
|
|
value: Optional[float] = Field(
|
|
default=None,
|
|
description="Valoarea calculată a indicatorului"
|
|
)
|
|
status: str = Field(
|
|
default="warning",
|
|
description="Statusul: 'good', 'warning', sau 'danger'"
|
|
)
|
|
threshold_min: Optional[float] = Field(
|
|
default=None,
|
|
description="Pragul minim pentru status 'good'"
|
|
)
|
|
threshold_max: Optional[float] = Field(
|
|
default=None,
|
|
description="Pragul maxim pentru status 'good'"
|
|
)
|
|
message: Optional[str] = Field(
|
|
default=None,
|
|
description="Mesaj explicativ pentru cazuri speciale"
|
|
)
|
|
sparkline_data: Optional[List[Optional[float]]] = Field(
|
|
default=None,
|
|
description="Array cu valorile indicatorului pe ultimele 12 luni (pentru sparkline)"
|
|
)
|
|
sparkline_labels: Optional[List[str]] = Field(
|
|
default=None,
|
|
description="Array cu etichetele lunilor în format 'MMM YY' (ex: 'Feb 24', 'Mar 24')"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"value": 1.25,
|
|
"status": "good",
|
|
"threshold_min": 1.0,
|
|
"threshold_max": None,
|
|
"message": None,
|
|
"sparkline_data": [1.15, 1.18, 1.20, 1.22, 1.19, 1.21, 1.23, 1.25, 1.24, 1.26, 1.25, 1.25],
|
|
"sparkline_labels": ["Feb 24", "Mar 24", "Apr 24", "May 24", "Jun 24", "Jul 24", "Aug 24", "Sep 24", "Oct 24", "Nov 24", "Dec 24", "Jan 25"]
|
|
}
|
|
}
|
|
|
|
|
|
class LiquidityIndicators(BaseModel):
|
|
"""
|
|
Indicatori de lichiditate pentru evaluarea capacității de plată
|
|
a datoriilor pe termen scurt.
|
|
|
|
Attributes:
|
|
lichiditate_curenta: Current Ratio = active_curente / datorii_curente
|
|
- Măsoară capacitatea de a plăti datoriile pe termen scurt cu active curente
|
|
- Good: >= 2.0, Warning: 1.0-2.0, Danger: < 1.0
|
|
|
|
lichiditate_imediata: Quick Ratio = (disponibilități + creanțe) / datorii_curente
|
|
- Măsoară capacitatea de plată fără a depinde de vânzarea stocurilor
|
|
- Good: >= 1.0, Warning: 0.5-1.0, Danger: < 0.5
|
|
|
|
lichiditate_vedere: Cash Ratio = disponibilități / datorii_curente
|
|
- Măsoară capacitatea de plată imediată doar din numerar
|
|
- Good: >= 0.2, Warning: 0.1-0.2, Danger: < 0.1
|
|
"""
|
|
lichiditate_curenta: IndicatorResult = Field(
|
|
description="Current Ratio = active_curente / datorii_curente"
|
|
)
|
|
lichiditate_imediata: IndicatorResult = Field(
|
|
description="Quick Ratio = (disponibilități + creanțe) / datorii_curente"
|
|
)
|
|
lichiditate_vedere: IndicatorResult = Field(
|
|
description="Cash Ratio = disponibilități / datorii_curente"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"lichiditate_curenta": {
|
|
"value": 2.37,
|
|
"status": "good",
|
|
"threshold_min": 2.0,
|
|
"threshold_max": None
|
|
},
|
|
"lichiditate_imediata": {
|
|
"value": 1.50,
|
|
"status": "good",
|
|
"threshold_min": 1.0,
|
|
"threshold_max": None
|
|
},
|
|
"lichiditate_vedere": {
|
|
"value": 0.45,
|
|
"status": "good",
|
|
"threshold_min": 0.2,
|
|
"threshold_max": None
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class EfficiencyIndicators(BaseModel):
|
|
"""
|
|
Indicatori de eficiență pentru evaluarea vitezei de conversie
|
|
a resurselor în numerar (working capital efficiency).
|
|
|
|
Attributes:
|
|
dso: Days Sales Outstanding (Durata medie de încasare)
|
|
- Formula: (clienti_sold / facturari_lunare) * 30
|
|
- Măsoară câte zile durează în medie încasarea creanțelor
|
|
- Good: < 30 zile, Warning: 30-45 zile, Danger: > 45 zile
|
|
|
|
dpo: Days Payables Outstanding (Durata medie de plată)
|
|
- Formula: (furnizori_sold / achizitii_lunare) * 30
|
|
- Măsoară câte zile durează în medie plata furnizorilor
|
|
- Valoare mai mare = folosim mai mult creditul furnizorilor
|
|
|
|
cash_conversion_cycle: Ciclu de conversie a numerarului
|
|
- Formula: DSO - DPO
|
|
- Pozitiv = numerar blocat în ciclul de afaceri
|
|
- Negativ = folosim creditul furnizorilor (favorabil)
|
|
|
|
rata_incasare: Rata de încasare (Collection Rate)
|
|
- Formula: incasari / facturari * 100
|
|
- Măsoară ce procent din facturări s-a încasat
|
|
- Good: >= 95%, Warning: 80-95%, Danger: < 80%
|
|
|
|
rata_plata: Rata de plată (Payment Rate)
|
|
- Formula: plati / achizitii * 100
|
|
- Măsoară ce procent din achiziții s-a achitat
|
|
"""
|
|
dso: IndicatorResult = Field(
|
|
description="Days Sales Outstanding = (clienti_sold / facturari_lunare) * 30"
|
|
)
|
|
dpo: IndicatorResult = Field(
|
|
description="Days Payables Outstanding = (furnizori_sold / achizitii_lunare) * 30"
|
|
)
|
|
cash_conversion_cycle: IndicatorResult = Field(
|
|
description="Cash Conversion Cycle = DSO - DPO"
|
|
)
|
|
rata_incasare: IndicatorResult = Field(
|
|
description="Rata de încasare = incasari / facturari * 100"
|
|
)
|
|
rata_plata: IndicatorResult = Field(
|
|
description="Rata de plată = plati / achizitii * 100"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"dso": {
|
|
"value": 28.5,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 30
|
|
},
|
|
"dpo": {
|
|
"value": 35.2,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": None,
|
|
"message": "Folosim bine creditul furnizorilor"
|
|
},
|
|
"cash_conversion_cycle": {
|
|
"value": -6.7,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 0,
|
|
"message": "Ciclu negativ = finanțare gratuită de la furnizori"
|
|
},
|
|
"rata_incasare": {
|
|
"value": 92.5,
|
|
"status": "warning",
|
|
"threshold_min": 95,
|
|
"threshold_max": None
|
|
},
|
|
"rata_plata": {
|
|
"value": 88.3,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": None
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class RiskIndicators(BaseModel):
|
|
"""
|
|
Indicatori de risc și aging pentru evaluarea sănătății
|
|
portofoliului de creanțe și datorii.
|
|
|
|
Attributes:
|
|
creante_restante_pct: Procentul creanțelor restante din total clienți
|
|
- Formula: clienti_sold_restant / clienti_sold_total * 100
|
|
- Măsoară ce procent din creanțe sunt depășite ca termen
|
|
- Good: < 20%, Warning: 20-30%, Danger: > 30%
|
|
|
|
creante_90plus_pct: Procentul creanțelor restante > 90 zile din total
|
|
- Formula: clienti_restant_90plus / clienti_sold_total * 100
|
|
- Indică creanțele cu risc mare de nerecuperare
|
|
- Good: < 5%, Warning: 5-10%, Danger: > 10%
|
|
|
|
datorii_restante_pct: Procentul datoriilor restante din total furnizori
|
|
- Formula: furnizori_sold_restant / furnizori_sold_total * 100
|
|
- Măsoară nivelul de întârzieri la plată
|
|
- Good: < 10%, Warning: 10-20%, Danger: > 20%
|
|
|
|
raport_datorii_trezorerie: Raportul între datorii furnizori și trezorerie
|
|
- Formula: furnizori_sold_total / trezorerie
|
|
- Indică câte luni de cash sunt necesare pentru a plăti furnizorii
|
|
- Good: < 2, Warning: 2-4, Danger: > 4
|
|
"""
|
|
creante_restante_pct: IndicatorResult = Field(
|
|
description="Procentul creanțelor restante = clienti_sold_restant / clienti_sold_total * 100"
|
|
)
|
|
creante_90plus_pct: IndicatorResult = Field(
|
|
description="Procentul creanțelor > 90 zile = clienti_restant_90plus / clienti_sold_total * 100"
|
|
)
|
|
datorii_restante_pct: IndicatorResult = Field(
|
|
description="Procentul datoriilor restante = furnizori_sold_restant / furnizori_sold_total * 100"
|
|
)
|
|
raport_datorii_trezorerie: IndicatorResult = Field(
|
|
description="Raport datorii/trezorerie = furnizori_sold_total / trezorerie"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"creante_restante_pct": {
|
|
"value": 15.5,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 20
|
|
},
|
|
"creante_90plus_pct": {
|
|
"value": 3.2,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 5
|
|
},
|
|
"datorii_restante_pct": {
|
|
"value": 8.5,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 10
|
|
},
|
|
"raport_datorii_trezorerie": {
|
|
"value": 1.8,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": 2,
|
|
"message": "Trezorerie suficientă pentru acoperirea datoriilor"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class CashFlowIndicators(BaseModel):
|
|
"""
|
|
Indicatori de cash flow pentru evaluarea generării și consumului de numerar.
|
|
|
|
Attributes:
|
|
flux_net_lunar: Fluxul net de numerar lunar (încasări - plăți)
|
|
- Formula: incasari_luna - plati_luna
|
|
- Pozitiv = firma generează numerar, Negativ = firma consumă numerar
|
|
- Good: > 0, Danger: < 0
|
|
|
|
cash_flow_ytd: Fluxul de numerar cumulat de la începutul anului (Year-To-Date)
|
|
- Formula: suma fluxurilor nete de la ianuarie până la luna curentă
|
|
- Arată tendința generală a anului în curs
|
|
|
|
flux_net_yoy_pct: Variația procentuală YoY (Year-over-Year)
|
|
- Formula: (cf_curent - cf_anterior) / abs(cf_anterior) * 100
|
|
- Compară cash flow-ul curent cu aceeași perioadă din anul anterior
|
|
|
|
acoperire_cash_flow: Rata de acoperire a datoriilor restante
|
|
- Formula: cash_flow_ytd / datorii_restante
|
|
- Arată de câte ori cash flow-ul YTD poate acoperi datoriile restante
|
|
- Good: > 1 (cash flow suficient), Danger: < 0.5
|
|
"""
|
|
flux_net_lunar: IndicatorResult = Field(
|
|
description="Flux net lunar = incasari_luna - plati_luna"
|
|
)
|
|
cash_flow_ytd: IndicatorResult = Field(
|
|
description="Cash flow cumulat YTD = suma fluxurilor de la ianuarie"
|
|
)
|
|
flux_net_yoy_pct: IndicatorResult = Field(
|
|
description="Variația YoY = (cf_curent - cf_anterior) / abs(cf_anterior) * 100"
|
|
)
|
|
acoperire_cash_flow: IndicatorResult = Field(
|
|
description="Acoperire datorii = cash_flow_ytd / datorii_restante"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"flux_net_lunar": {
|
|
"value": 125000.50,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None,
|
|
"message": "Firma generează numerar"
|
|
},
|
|
"cash_flow_ytd": {
|
|
"value": 850000.00,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None
|
|
},
|
|
"flux_net_yoy_pct": {
|
|
"value": 15.5,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None,
|
|
"message": "Creștere cash flow față de anul anterior"
|
|
},
|
|
"acoperire_cash_flow": {
|
|
"value": 2.5,
|
|
"status": "good",
|
|
"threshold_min": 1.0,
|
|
"threshold_max": None,
|
|
"message": "Cash flow suficient pentru acoperirea datoriilor"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class DynamicsIndicators(BaseModel):
|
|
"""
|
|
Indicatori de dinamică pentru evaluarea evoluției vânzărilor și achizițiilor.
|
|
|
|
Arată dacă afacerea crește sau scade prin comparație YoY (Year-over-Year).
|
|
|
|
Attributes:
|
|
crestere_vanzari_yoy: Creșterea procentuală a vânzărilor față de anul anterior
|
|
- Formula: (facturari_curent - facturari_anterior) / facturari_anterior * 100
|
|
- Măsoară dinamica vânzărilor - creștere sau scădere
|
|
- Good: > 5%, Warning: 0-5%, Danger: < 0%
|
|
|
|
crestere_achizitii_yoy: Creșterea procentuală a achizițiilor față de anul anterior
|
|
- Formula: (achizitii_curent - achizitii_anterior) / achizitii_anterior * 100
|
|
- Creșterea achizițiilor poate indica expansiune sau costuri mai mari
|
|
|
|
marja_implicita: Marja implicită din diferența facturări - achiziții
|
|
- Formula: (facturari - achizitii) / facturari * 100
|
|
- Arată ce procent din vânzări rămâne după achiziții
|
|
- Good: > 20%, Warning: 10-20%, Danger: < 10%
|
|
"""
|
|
crestere_vanzari_yoy: IndicatorResult = Field(
|
|
description="Creștere vânzări YoY = (facturari_curent - facturari_anterior) / facturari_anterior * 100"
|
|
)
|
|
crestere_achizitii_yoy: IndicatorResult = Field(
|
|
description="Creștere achiziții YoY = (achizitii_curent - achizitii_anterior) / achizitii_anterior * 100"
|
|
)
|
|
marja_implicita: IndicatorResult = Field(
|
|
description="Marja implicită = (facturari - achizitii) / facturari * 100"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"crestere_vanzari_yoy": {
|
|
"value": 12.5,
|
|
"status": "good",
|
|
"threshold_min": 5.0,
|
|
"threshold_max": None,
|
|
"message": "Creștere semnificativă a vânzărilor"
|
|
},
|
|
"crestere_achizitii_yoy": {
|
|
"value": 8.3,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": None,
|
|
"message": "Achiziții în creștere"
|
|
},
|
|
"marja_implicita": {
|
|
"value": 25.5,
|
|
"status": "good",
|
|
"threshold_min": 20.0,
|
|
"threshold_max": None,
|
|
"message": "Marjă implicită sănătoasă"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class AltmanZScore(BaseModel):
|
|
"""
|
|
Altman Z-Score pentru evaluarea riscului de faliment.
|
|
|
|
Folosim formula modificată pentru companii private (Z'-Score):
|
|
Z' = 6.56*X1 + 3.26*X2 + 6.72*X3 + 1.05*X4
|
|
|
|
Coeficienții sunt specifici pentru companii care nu sunt listate la bursă,
|
|
unde se folosește valoarea contabilă a capitalurilor proprii în loc de
|
|
valoarea de piață a acțiunilor.
|
|
|
|
Componente:
|
|
X1: Working Capital / Total Assets
|
|
- Măsoară lichiditatea pe termen scurt
|
|
- Working capital = active curente - datorii curente
|
|
|
|
X2: Retained Earnings / Total Assets
|
|
- Măsoară profitabilitatea cumulată (rezultat reportat)
|
|
- Include conturile 117 și 121 (rezultat reportat + rezultat curent)
|
|
|
|
X3: EBIT / Total Assets
|
|
- Măsoară eficiența operațională
|
|
- EBIT = venituri din exploatare - cheltuieli operaționale
|
|
|
|
X4: Book Value of Equity / Total Liabilities
|
|
- Măsoară solvabilitatea (acoperirea datoriilor cu capital propriu)
|
|
- Capital propriu / (datorii curente + datorii termen lung)
|
|
|
|
Zone de risc:
|
|
- Safe Zone (zscore > 2.60): Risc minim de faliment
|
|
- Grey Zone (1.10 <= zscore <= 2.60): Risc moderat, necesită atenție
|
|
- Distress Zone (zscore < 1.10): Risc ridicat de faliment
|
|
|
|
Attributes:
|
|
zscore: Scorul Altman Z calculat
|
|
status: Zona de risc ('safe', 'grey', sau 'distress')
|
|
x1: Componenta X1 (Working Capital / Total Assets)
|
|
x2: Componenta X2 (Retained Earnings / Total Assets)
|
|
x3: Componenta X3 (EBIT / Total Assets)
|
|
x4: Componenta X4 (Equity / Total Liabilities)
|
|
working_capital: Fondul de rulment (active curente - datorii curente)
|
|
total_assets: Total active
|
|
"""
|
|
zscore: IndicatorResult = Field(
|
|
description="Scorul Altman Z = 6.56*X1 + 3.26*X2 + 6.72*X3 + 1.05*X4"
|
|
)
|
|
x1: IndicatorResult = Field(
|
|
description="X1 = Working Capital / Total Assets (lichiditate)"
|
|
)
|
|
x2: IndicatorResult = Field(
|
|
description="X2 = Retained Earnings / Total Assets (profitabilitate)"
|
|
)
|
|
x3: IndicatorResult = Field(
|
|
description="X3 = EBIT / Total Assets (eficiență operațională)"
|
|
)
|
|
x4: IndicatorResult = Field(
|
|
description="X4 = Capitaluri Proprii / Datorii Totale (solvabilitate)"
|
|
)
|
|
# Valori absolute pentru verificare manuală în balanță
|
|
capital_de_lucru: IndicatorResult = Field(
|
|
description="Capital de lucru = Active Curente - Datorii Curente"
|
|
)
|
|
active_totale: IndicatorResult = Field(
|
|
description="Active Totale = Active Imobilizate + Active Curente"
|
|
)
|
|
datorii_totale: IndicatorResult = Field(
|
|
description="Datorii Totale = Datorii Curente + Datorii Termen Lung"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"zscore": {
|
|
"value": 3.25,
|
|
"status": "safe",
|
|
"threshold_min": 2.60,
|
|
"threshold_max": None,
|
|
"message": "Zona sigură - risc minim de faliment"
|
|
},
|
|
"x1": {
|
|
"value": 0.25,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None
|
|
},
|
|
"x2": {
|
|
"value": 0.15,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None
|
|
},
|
|
"x3": {
|
|
"value": 0.12,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None
|
|
},
|
|
"x4": {
|
|
"value": 1.80,
|
|
"status": "good",
|
|
"threshold_min": 1.0,
|
|
"threshold_max": None
|
|
},
|
|
"capital_de_lucru": {
|
|
"value": 450000.00,
|
|
"status": "good",
|
|
"message": "Active Curente - Datorii Curente"
|
|
},
|
|
"active_totale": {
|
|
"value": 1800000.00,
|
|
"status": "good",
|
|
"message": "Active Imobilizate + Active Curente"
|
|
},
|
|
"datorii_totale": {
|
|
"value": 1200000.00,
|
|
"status": "good",
|
|
"message": "Datorii Curente + Datorii Termen Lung"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class ProfitabilityIndicators(BaseModel):
|
|
"""
|
|
Indicatori de profitabilitate pentru evaluarea randamentului afacerii.
|
|
|
|
Calculează indicatori cheie pentru evaluarea profitabilității pe baza
|
|
datelor din balanța de verificare (VBAL): venituri, cheltuieli, active, capital.
|
|
|
|
Attributes:
|
|
cifra_afaceri: Total venituri din activitatea operațională (Clasa 7)
|
|
- Reprezintă volumul total al vânzărilor
|
|
- Sursa: suma conturilor 70x-75x din VBAL
|
|
|
|
cheltuieli_totale: Total cheltuieli operaționale (Clasa 6)
|
|
- Reprezintă costurile activității
|
|
- Sursa: suma conturilor 60x-65x din VBAL
|
|
|
|
profit_brut: Diferența dintre venituri și cheltuieli (EBIT)
|
|
- Formula: cifra_afaceri - cheltuieli_totale
|
|
- Good: > 0, Danger: < 0
|
|
|
|
marja_profit_brut: Procentul de profit din vânzări
|
|
- Formula: profit_brut / cifra_afaceri * 100
|
|
- Good: > 10%, Warning: 5-10%, Danger: < 5%
|
|
|
|
roa: Return on Assets - randamentul activelor
|
|
- Formula: profit_brut / total_active * 100
|
|
- Măsoară eficiența utilizării activelor
|
|
- Good: > 5%, Warning: 2-5%, Danger: < 2%
|
|
|
|
roe: Return on Equity - randamentul capitalului propriu
|
|
- Formula: profit_brut / capitaluri_proprii * 100
|
|
- Măsoară randamentul pentru acționari
|
|
- Good: > 10%, Warning: 5-10%, Danger: < 5%
|
|
"""
|
|
cifra_afaceri: IndicatorResult = Field(
|
|
description="Cifra de afaceri = Total venituri operaționale (Clasa 7)"
|
|
)
|
|
# Cheltuieli separate pentru verificare
|
|
cheltuieli_operationale: IndicatorResult = Field(
|
|
description="Cheltuieli operaționale = Clasa 60x-65x + 68x (fără dobânzi 66x)"
|
|
)
|
|
cheltuieli_financiare: IndicatorResult = Field(
|
|
description="Cheltuieli financiare = Clasa 66x (dobânzi, diferențe curs valutar)"
|
|
)
|
|
cheltuieli_totale: IndicatorResult = Field(
|
|
description="Cheltuieli totale = Operaționale + Financiare"
|
|
)
|
|
profit_brut: IndicatorResult = Field(
|
|
description="Profit brut (EBIT) = Venituri - Cheltuieli operaționale"
|
|
)
|
|
marja_profit_brut: IndicatorResult = Field(
|
|
description="Marja de profit = Profit brut / Cifra afaceri * 100"
|
|
)
|
|
# Indicatori de bază pentru verificare ROA/ROE
|
|
active_totale: IndicatorResult = Field(
|
|
description="Active Totale - bază calcul ROA"
|
|
)
|
|
capitaluri_proprii: IndicatorResult = Field(
|
|
description="Capitaluri Proprii - bază calcul ROE"
|
|
)
|
|
roa: IndicatorResult = Field(
|
|
description="Randament Active (ROA) = Profit / Active Totale * 100"
|
|
)
|
|
roe: IndicatorResult = Field(
|
|
description="Randament Capitaluri (ROE) = Profit / Capital Propriu * 100"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"cifra_afaceri": {
|
|
"value": 2500000.00,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": None
|
|
},
|
|
"cheltuieli_totale": {
|
|
"value": 2100000.00,
|
|
"status": "good",
|
|
"threshold_min": None,
|
|
"threshold_max": None
|
|
},
|
|
"profit_brut": {
|
|
"value": 400000.00,
|
|
"status": "good",
|
|
"threshold_min": 0,
|
|
"threshold_max": None,
|
|
"message": "Profit operațional pozitiv"
|
|
},
|
|
"marja_profit_brut": {
|
|
"value": 16.0,
|
|
"status": "good",
|
|
"threshold_min": 10.0,
|
|
"threshold_max": None
|
|
},
|
|
"roa": {
|
|
"value": 8.5,
|
|
"status": "good",
|
|
"threshold_min": 5.0,
|
|
"threshold_max": None,
|
|
"message": "Randament bun al activelor"
|
|
},
|
|
"roe": {
|
|
"value": 15.2,
|
|
"status": "good",
|
|
"threshold_min": 10.0,
|
|
"threshold_max": None,
|
|
"message": "Randament atractiv pentru acționari"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
class FinancialIndicatorsResponse(BaseModel):
|
|
"""
|
|
Răspunsul complet al endpoint-ului /api/reports/dashboard/financial-indicators.
|
|
|
|
Agregă toți indicatorii financiari calculați pentru o firmă și perioadă dată.
|
|
Acest model este folosit pentru serializarea JSON a răspunsului API.
|
|
|
|
Attributes:
|
|
lichiditate: Indicatori de lichiditate (Current Ratio, Quick Ratio, Cash Ratio)
|
|
eficienta: Indicatori de eficiență (DSO, DPO, CCC, rate încasare/plată)
|
|
risc: Indicatori de risc (creanțe/datorii restante, raport datorii/trezorerie)
|
|
cash_flow: Indicatori de cash flow (flux net lunar, YTD, YoY, acoperire)
|
|
dinamica: Indicatori de dinamică (creștere vânzări/achiziții YoY, marjă)
|
|
altman_zscore: Scorul Altman Z-Score și componentele X1-X4
|
|
profitabilitate: Indicatori de profitabilitate (ROA, ROE, marjă profit)
|
|
|
|
Usage:
|
|
GET /api/reports/dashboard/financial-indicators?company=123&luna=12&an=2024
|
|
|
|
Response example:
|
|
{
|
|
"lichiditate": { ... },
|
|
"eficienta": { ... },
|
|
"risc": { ... },
|
|
"cash_flow": { ... },
|
|
"dinamica": { ... },
|
|
"altman_zscore": { ... },
|
|
"profitabilitate": { ... }
|
|
}
|
|
"""
|
|
lichiditate: LiquidityIndicators = Field(
|
|
description="Indicatori de lichiditate: Current Ratio, Quick Ratio, Cash Ratio"
|
|
)
|
|
eficienta: EfficiencyIndicators = Field(
|
|
description="Indicatori de eficiență: DSO, DPO, CCC, rate încasare/plată"
|
|
)
|
|
risc: RiskIndicators = Field(
|
|
description="Indicatori de risc: creanțe/datorii restante, raport datorii/trezorerie"
|
|
)
|
|
cash_flow: CashFlowIndicators = Field(
|
|
description="Indicatori de cash flow: flux net lunar, YTD, YoY, acoperire"
|
|
)
|
|
dinamica: DynamicsIndicators = Field(
|
|
description="Indicatori de dinamică: creștere vânzări/achiziții YoY, marjă implicită"
|
|
)
|
|
altman_zscore: AltmanZScore = Field(
|
|
description="Altman Z-Score și componentele X1-X4"
|
|
)
|
|
profitabilitate: ProfitabilityIndicators = Field(
|
|
description="Indicatori de profitabilitate: ROA, ROE, marja de profit"
|
|
)
|
|
|
|
class Config:
|
|
json_schema_extra = {
|
|
"example": {
|
|
"lichiditate": {
|
|
"lichiditate_curenta": {"value": 2.37, "status": "good", "threshold_min": 2.0},
|
|
"lichiditate_imediata": {"value": 1.50, "status": "good", "threshold_min": 1.0},
|
|
"lichiditate_vedere": {"value": 0.45, "status": "good", "threshold_min": 0.2}
|
|
},
|
|
"eficienta": {
|
|
"dso": {"value": 28.5, "status": "good", "threshold_max": 30},
|
|
"dpo": {"value": 35.2, "status": "good"},
|
|
"cash_conversion_cycle": {"value": -6.7, "status": "good", "threshold_max": 0},
|
|
"rata_incasare": {"value": 92.5, "status": "warning", "threshold_min": 95},
|
|
"rata_plata": {"value": 88.3, "status": "good"}
|
|
},
|
|
"risc": {
|
|
"creante_restante_pct": {"value": 15.5, "status": "good", "threshold_max": 20},
|
|
"creante_90plus_pct": {"value": 3.2, "status": "good", "threshold_max": 5},
|
|
"datorii_restante_pct": {"value": 8.5, "status": "good", "threshold_max": 10},
|
|
"raport_datorii_trezorerie": {"value": 1.8, "status": "good", "threshold_max": 2}
|
|
},
|
|
"cash_flow": {
|
|
"flux_net_lunar": {"value": 125000.50, "status": "good", "threshold_min": 0},
|
|
"cash_flow_ytd": {"value": 850000.00, "status": "good", "threshold_min": 0},
|
|
"flux_net_yoy_pct": {"value": 15.5, "status": "good", "threshold_min": 0},
|
|
"acoperire_cash_flow": {"value": 2.5, "status": "good", "threshold_min": 1.0}
|
|
},
|
|
"dinamica": {
|
|
"crestere_vanzari_yoy": {"value": 12.5, "status": "good", "threshold_min": 5.0},
|
|
"crestere_achizitii_yoy": {"value": 8.3, "status": "good"},
|
|
"marja_implicita": {"value": 25.5, "status": "good", "threshold_min": 20.0}
|
|
},
|
|
"altman_zscore": {
|
|
"zscore": {"value": 3.25, "status": "safe", "threshold_min": 2.60},
|
|
"x1": {"value": 0.25, "status": "good"},
|
|
"x2": {"value": 0.15, "status": "good"},
|
|
"x3": {"value": 0.12, "status": "good"},
|
|
"x4": {"value": 1.80, "status": "good"},
|
|
"working_capital": 450000.00,
|
|
"total_assets": 1800000.00
|
|
}
|
|
}
|
|
}
|