feat(dashboard): Complete dashboard desktop cleanup and improvements
User Stories Completed: - US-001: Eliminare SolduriCompactCard de pe Desktop - US-002: Eliminare Icoane din Header-ul CollapsibleCard - US-003: Reorganizare TreasuryDualCard - Text Înainte de Grafice - US-004: Reorganizare ClientiBalanceCard - Text Înainte de Grafice - US-005: Reorganizare FurnizoriBalanceCard - Text Înainte de Grafice - US-006: Grafice Colapsabile în TreasuryDualCard - US-007: Grafice Colapsabile în ClientiBalanceCard - US-008: Grafice Colapsabile în FurnizoriBalanceCard - US-009: Grafice Colapsabile în CashFlowMetricCard Additional Improvements: - Add cache metadata display (CacheFooter component) for all dashboard cards - Add @cached decorators to get_monthly_flows and get_indicators_with_sparklines - Fix financial indicators calculations and sparkline sync - Add state reset on company change to prevent stale data - New shared components: CacheFooter.vue, authRedirect.js - Enhanced FinancialIndicatorsCard with sparklines and period selection Squashed from branch: ralph/dashboard-desktop-cleanup (11 commits) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -89,6 +89,18 @@ class BalanceSheetAggregates(BaseModel):
|
||||
default=Decimal('0'),
|
||||
description="Cheltuieli financiare (Clasa 66 - dobânzi, diferențe curs)"
|
||||
)
|
||||
capital_social_strict: Decimal = Field(
|
||||
default=Decimal('0'),
|
||||
description="Capital Social strict (doar contul 101 - subscris și vărsat)"
|
||||
)
|
||||
cifra_afaceri: Decimal = Field(
|
||||
default=Decimal('0'),
|
||||
description="Cifra de afaceri (doar 70x FĂRĂ TVA, fără 71x-75x)"
|
||||
)
|
||||
achizitii_stocuri: Decimal = Field(
|
||||
default=Decimal('0'),
|
||||
description="Achiziții stocuri YTD (Clasa 3 TOTDEB, FĂRĂ TVA)"
|
||||
)
|
||||
|
||||
# Computed properties pentru calculele ulterioare
|
||||
@property
|
||||
@@ -220,6 +232,12 @@ class LiquidityIndicators(BaseModel):
|
||||
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
|
||||
|
||||
Sub-indicatori pentru verificare:
|
||||
- active_curente: Active Curente = Stocuri + Creanțe + Disponibilități
|
||||
- disponibilitati: Disponibilități (bancă + casă)
|
||||
- creante: Creanțe comerciale
|
||||
- datorii_curente: Datorii pe termen scurt
|
||||
"""
|
||||
lichiditate_curenta: IndicatorResult = Field(
|
||||
description="Current Ratio = active_curente / datorii_curente"
|
||||
@@ -230,6 +248,23 @@ class LiquidityIndicators(BaseModel):
|
||||
lichiditate_vedere: IndicatorResult = Field(
|
||||
description="Cash Ratio = disponibilități / datorii_curente"
|
||||
)
|
||||
# Sub-indicatori pentru verificare manuală în balanță
|
||||
active_curente: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Active Curente = Stocuri + Creanțe + Disponibilități (RON)"
|
||||
)
|
||||
disponibilitati: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Disponibilități = Bancă (512x) + Casă (531x) (RON)"
|
||||
)
|
||||
creante: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Creanțe comerciale = Clienți (411x) + Debitori (461x) (RON)"
|
||||
)
|
||||
datorii_curente: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Datorii pe termen scurt = Furnizori + TVA + Salarii etc. (RON)"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -301,6 +336,31 @@ class EfficiencyIndicators(BaseModel):
|
||||
rata_plata: IndicatorResult = Field(
|
||||
description="Rata de plată = plati / achizitii * 100"
|
||||
)
|
||||
# Sub-indicatori pentru verificare manuală
|
||||
sold_clienti: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold Clienți la final de lună (RON)"
|
||||
)
|
||||
facturari_lunare: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total facturări în luna curentă (RON)"
|
||||
)
|
||||
sold_furnizori: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold Furnizori la final de lună (RON)"
|
||||
)
|
||||
achizitii_lunare: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total achiziții în luna curentă (RON)"
|
||||
)
|
||||
incasari_luna: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Încasări efectuate în luna curentă (RON)"
|
||||
)
|
||||
plati_luna: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Plăți efectuate în luna curentă (RON)"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -379,6 +439,31 @@ class RiskIndicators(BaseModel):
|
||||
raport_datorii_trezorerie: IndicatorResult = Field(
|
||||
description="Raport datorii/trezorerie = furnizori_sold_total / trezorerie"
|
||||
)
|
||||
# Sub-indicatori pentru verificare manuală
|
||||
total_clienti: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold total clienți (411x) (RON)"
|
||||
)
|
||||
clienti_restanti: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold clienți cu facturi restante (RON)"
|
||||
)
|
||||
clienti_90plus: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold clienți cu facturi >90 zile restant (RON)"
|
||||
)
|
||||
total_furnizori: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold total furnizori (401x) (RON)"
|
||||
)
|
||||
furnizori_restanti: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Sold furnizori cu facturi restante (RON)"
|
||||
)
|
||||
trezorerie: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Disponibilități (512x + 531x) (RON)"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -447,6 +532,23 @@ class CashFlowIndicators(BaseModel):
|
||||
acoperire_cash_flow: IndicatorResult = Field(
|
||||
description="Acoperire datorii = cash_flow_ytd / datorii_restante"
|
||||
)
|
||||
# Sub-indicatori pentru verificare manuală
|
||||
incasari_luna: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Încasări luna curentă (RON)"
|
||||
)
|
||||
plati_luna: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Plăți luna curentă (RON)"
|
||||
)
|
||||
cf_an_precedent: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Cash Flow aceeași perioadă an precedent (RON)"
|
||||
)
|
||||
datorii_restante: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total datorii cu scadență depășită (RON)"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -488,19 +590,24 @@ class DynamicsIndicators(BaseModel):
|
||||
|
||||
Arată dacă afacerea crește sau scade prin comparație YoY (Year-over-Year).
|
||||
|
||||
SURSE DE DATE (toate FĂRĂ TVA):
|
||||
- Vânzări: Cifra de Afaceri din VBAL (Clasa 7 - conturile 70x)
|
||||
- Achiziții: Registru Jurnal ACT (stocuri 3x=4x + cheltuieli directe 6x=4x)
|
||||
|
||||
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
|
||||
crestere_vanzari_yoy: Creșterea procentuală a Cifrei de Afaceri față de anul anterior
|
||||
- Formula: (CA_curent - CA_anterior) / CA_anterior * 100
|
||||
- Sursa: VBAL TOTCRED(70x) - TOTDEB(709)
|
||||
- Good: > 5%, Warning: 0-5%, Danger: < 0%
|
||||
|
||||
crestere_achizitii_yoy: Creșterea procentuală a achizițiilor față de anul anterior
|
||||
crestere_achizitii_yoy: Creșterea procentuală a achizițiilor totale față de anul anterior
|
||||
- Formula: (achizitii_curent - achizitii_anterior) / achizitii_anterior * 100
|
||||
- Sursa: ACT (stocuri 3x=4x + cheltuieli directe 6x=4x, fără TVA)
|
||||
- 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
|
||||
marja_implicita: Marja implicită din diferența CA - achiziții totale
|
||||
- Formula: (CA - achizitii_totale) / CA * 100
|
||||
- Arată ce procent din Cifra de Afaceri rămâne după achiziții
|
||||
- Good: > 20%, Warning: 10-20%, Danger: < 10%
|
||||
"""
|
||||
crestere_vanzari_yoy: IndicatorResult = Field(
|
||||
@@ -512,6 +619,23 @@ class DynamicsIndicators(BaseModel):
|
||||
marja_implicita: IndicatorResult = Field(
|
||||
description="Marja implicită = (facturari - achizitii) / facturari * 100"
|
||||
)
|
||||
# Sub-indicatori pentru verificare manuală
|
||||
vanzari_an_curent: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total vânzări YTD an curent (RON)"
|
||||
)
|
||||
vanzari_an_precedent: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total vânzări YTD an precedent (RON)"
|
||||
)
|
||||
achizitii_an_curent: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total achiziții YTD an curent (stocuri + cheltuieli directe, fără TVA)"
|
||||
)
|
||||
achizitii_an_precedent: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total achiziții YTD an precedent (stocuri + cheltuieli directe, fără TVA)"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -713,6 +837,11 @@ class ProfitabilityIndicators(BaseModel):
|
||||
profit_brut: IndicatorResult = Field(
|
||||
description="Profit brut (EBIT) = Venituri - Cheltuieli operaționale"
|
||||
)
|
||||
# Sub-indicator pentru verificare EBIT
|
||||
venituri: Optional[IndicatorResult] = Field(
|
||||
default=None,
|
||||
description="Total venituri (Clasa 7) - pentru verificare calcul EBIT (RON)"
|
||||
)
|
||||
marja_profit_brut: IndicatorResult = Field(
|
||||
description="Marja de profit = Profit brut / Cifra afaceri * 100"
|
||||
)
|
||||
@@ -776,6 +905,91 @@ class ProfitabilityIndicators(BaseModel):
|
||||
}
|
||||
|
||||
|
||||
class SolvabilityIndicators(BaseModel):
|
||||
"""
|
||||
Indicatori de solvabilitate pentru evaluarea capacității firmei
|
||||
de a-și acoperi datoriile pe termen lung.
|
||||
|
||||
Conform articolului UniversulFiscal despre Activul Net Contabil (ANC):
|
||||
- ANC = Total Active - Total Datorii
|
||||
- Implicații legale (din 1 ianuarie 2026): Sub 50% din capital social
|
||||
→ restricții dividende, restituire împrumuturi, acordare împrumuturi noi
|
||||
|
||||
Attributes:
|
||||
activ_net_contabil: Activul Net Contabil (ANC) în RON
|
||||
- Formula: Total Active - Total Datorii
|
||||
- Good: > 0 (firma are avere netă pozitivă)
|
||||
- Danger: <= 0 (firma este insolvabilă tehnic)
|
||||
|
||||
rata_anc_capital: Rata ANC / Capital Social în %
|
||||
- Formula: (ANC / Capital Social) × 100
|
||||
- Good: >= 100% (ANC acoperă integral capitalul social)
|
||||
- Warning: 50-100% (ANC sub capital, dar peste pragul legal)
|
||||
- Danger: < 50% (sub pragul legal - restricții aplicabile)
|
||||
|
||||
total_active: Total Active - valoare de verificare
|
||||
total_datorii: Total Datorii - valoare de verificare
|
||||
capital_social: Capital Social - valoare de verificare
|
||||
"""
|
||||
activ_net_contabil: IndicatorResult = Field(
|
||||
description="Activ Net Contabil = Total Active - Total Datorii (RON)"
|
||||
)
|
||||
rata_anc_capital: IndicatorResult = Field(
|
||||
description="Rata ANC/Capital = (ANC / Capital Social) × 100 (%)"
|
||||
)
|
||||
# Valori de bază pentru verificare manuală în balanță
|
||||
total_active: IndicatorResult = Field(
|
||||
description="Total Active - bază calcul ANC"
|
||||
)
|
||||
total_datorii: IndicatorResult = Field(
|
||||
description="Total Datorii - bază calcul ANC"
|
||||
)
|
||||
capital_social: IndicatorResult = Field(
|
||||
description="Capital Social - bază calcul Rata ANC"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
"example": {
|
||||
"activ_net_contabil": {
|
||||
"value": 850000.00,
|
||||
"status": "good",
|
||||
"threshold_min": 0,
|
||||
"threshold_max": None,
|
||||
"message": "Activ net pozitiv - firma solvabilă"
|
||||
},
|
||||
"rata_anc_capital": {
|
||||
"value": 125.5,
|
||||
"status": "good",
|
||||
"threshold_min": 100.0,
|
||||
"threshold_max": None,
|
||||
"message": "ANC peste capitalul social - situație sănătoasă"
|
||||
},
|
||||
"total_active": {
|
||||
"value": 1800000.00,
|
||||
"status": "good",
|
||||
"threshold_min": None,
|
||||
"threshold_max": None,
|
||||
"message": "Active Imobilizate + Active Curente"
|
||||
},
|
||||
"total_datorii": {
|
||||
"value": 950000.00,
|
||||
"status": "good",
|
||||
"threshold_min": None,
|
||||
"threshold_max": None,
|
||||
"message": "Datorii Curente + Datorii Termen Lung"
|
||||
},
|
||||
"capital_social": {
|
||||
"value": 680000.00,
|
||||
"status": "good",
|
||||
"threshold_min": None,
|
||||
"threshold_max": None,
|
||||
"message": "Capital subscris și vărsat"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class FinancialIndicatorsResponse(BaseModel):
|
||||
"""
|
||||
Răspunsul complet al endpoint-ului /api/reports/dashboard/financial-indicators.
|
||||
@@ -791,6 +1005,7 @@ class FinancialIndicatorsResponse(BaseModel):
|
||||
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)
|
||||
solvabilitate: Indicatori de solvabilitate (ANC, rata ANC/Capital Social)
|
||||
|
||||
Usage:
|
||||
GET /api/reports/dashboard/financial-indicators?company=123&luna=12&an=2024
|
||||
@@ -803,7 +1018,8 @@ class FinancialIndicatorsResponse(BaseModel):
|
||||
"cash_flow": { ... },
|
||||
"dinamica": { ... },
|
||||
"altman_zscore": { ... },
|
||||
"profitabilitate": { ... }
|
||||
"profitabilitate": { ... },
|
||||
"solvabilitate": { ... }
|
||||
}
|
||||
"""
|
||||
lichiditate: LiquidityIndicators = Field(
|
||||
@@ -827,6 +1043,9 @@ class FinancialIndicatorsResponse(BaseModel):
|
||||
profitabilitate: ProfitabilityIndicators = Field(
|
||||
description="Indicatori de profitabilitate: ROA, ROE, marja de profit"
|
||||
)
|
||||
solvabilitate: SolvabilityIndicators = Field(
|
||||
description="Indicatori de solvabilitate: ANC, rata ANC/Capital Social"
|
||||
)
|
||||
|
||||
class Config:
|
||||
json_schema_extra = {
|
||||
@@ -868,6 +1087,13 @@ class FinancialIndicatorsResponse(BaseModel):
|
||||
"x4": {"value": 1.80, "status": "good"},
|
||||
"working_capital": 450000.00,
|
||||
"total_assets": 1800000.00
|
||||
},
|
||||
"solvabilitate": {
|
||||
"activ_net_contabil": {"value": 850000.00, "status": "good", "threshold_min": 0},
|
||||
"rata_anc_capital": {"value": 125.5, "status": "good", "threshold_min": 100.0},
|
||||
"total_active": {"value": 1800000.00, "status": "good"},
|
||||
"total_datorii": {"value": 950000.00, "status": "good"},
|
||||
"capital_social": {"value": 680000.00, "status": "good"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from typing import Optional
|
||||
# import sys # Removed - no longer needed
|
||||
import os
|
||||
|
||||
from shared.auth.dependencies import get_current_user
|
||||
@@ -290,6 +289,7 @@ async def get_maturity_analysis(
|
||||
|
||||
@router.get("/monthly-flows")
|
||||
async def get_monthly_flows(
|
||||
request: Request,
|
||||
company: int = Query(..., description="ID-ul firmei"),
|
||||
luna: Optional[int] = Query(None, ge=1, le=12, description="Luna contabilă (1-12)"),
|
||||
an: Optional[int] = Query(None, ge=2000, le=2100, description="Anul contabil"),
|
||||
@@ -301,15 +301,31 @@ async def get_monthly_flows(
|
||||
- Necesită autentificare JWT
|
||||
- Returnează date pentru analiza fluxurilor lunare
|
||||
- luna/an: perioada contabilă de referință (dacă nu sunt specificate, folosește ultima perioadă)
|
||||
- Include metadata cache pentru Telegram Bot (X-Include-Cache-Metadata header)
|
||||
"""
|
||||
try:
|
||||
# Verifică dacă utilizatorul are acces la firma specificată
|
||||
if str(company) not in current_user.companies:
|
||||
raise HTTPException(status_code=403, detail=f"Nu aveți acces la firma {company}")
|
||||
|
||||
result = await DashboardService.get_monthly_flows(company, luna=luna, an=an)
|
||||
return result
|
||||
|
||||
# Apelăm serviciul cu request pentru cache metadata
|
||||
result = await DashboardService.get_monthly_flows(company, luna=luna, an=an, request=request)
|
||||
|
||||
# Convert to dict if needed
|
||||
result_dict = result.dict() if hasattr(result, 'dict') else result
|
||||
|
||||
# Add cache metadata if requested (for Telegram Bot / Dashboard)
|
||||
include_metadata = request.headers.get('X-Include-Cache-Metadata', '').lower() == 'true'
|
||||
if include_metadata:
|
||||
cache_hit = getattr(request.state, 'cache_hit', False)
|
||||
response_time = getattr(request.state, 'response_time_ms', 0)
|
||||
cache_source = getattr(request.state, 'cache_source', None)
|
||||
result_dict['cache_hit'] = cache_hit
|
||||
result_dict['response_time_ms'] = response_time
|
||||
result_dict['cache_source'] = cache_source
|
||||
|
||||
return result_dict
|
||||
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
except Exception as e:
|
||||
@@ -435,7 +451,6 @@ async def get_current_period(
|
||||
|
||||
@router.get(
|
||||
"/financial-indicators",
|
||||
response_model=FinancialIndicatorsResponse,
|
||||
tags=["dashboard"]
|
||||
)
|
||||
async def get_financial_indicators(
|
||||
@@ -445,7 +460,7 @@ async def get_financial_indicators(
|
||||
an: Optional[int] = Query(None, ge=2000, le=2100, description="Anul contabil"),
|
||||
include_sparklines: bool = Query(True, description="Include date istorice pentru sparklines (12 luni)"),
|
||||
current_user: CurrentUser = Depends(get_current_user)
|
||||
) -> FinancialIndicatorsResponse:
|
||||
):
|
||||
"""
|
||||
Returnează toți indicatorii financiari calculați pentru firma selectată.
|
||||
|
||||
@@ -504,15 +519,25 @@ async def get_financial_indicators(
|
||||
# Dacă include_sparklines este True, folosim metoda care include datele istorice
|
||||
if include_sparklines:
|
||||
response = await FinancialIndicatorsService.get_indicators_with_sparklines(
|
||||
company, resolved_luna, resolved_an, months=12
|
||||
company, resolved_luna, resolved_an, months=12, request=request
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"Financial indicators with sparklines for company {company}, "
|
||||
f"luna={resolved_luna}, an={resolved_an}: "
|
||||
f"Z-Score={response.altman_zscore.zscore.value} ({response.altman_zscore.zscore.status})"
|
||||
f"Z-Score={response.altman_zscore.zscore.value} ({response.altman_zscore.zscore.status}), "
|
||||
f"cache_hit={getattr(request.state, 'cache_hit', False)}, "
|
||||
f"response_time={getattr(request.state, 'response_time_ms', 0):.1f}ms"
|
||||
)
|
||||
|
||||
# Add cache metadata if requested (for Telegram Bot / Dashboard)
|
||||
include_metadata = request.headers.get('X-Include-Cache-Metadata', '').lower() == 'true'
|
||||
if include_metadata:
|
||||
result_dict = response.dict() if hasattr(response, 'dict') else response
|
||||
result_dict['cache_hit'] = getattr(request.state, 'cache_hit', False)
|
||||
result_dict['response_time_ms'] = getattr(request.state, 'response_time_ms', 0)
|
||||
result_dict['cache_source'] = getattr(request.state, 'cache_source', None)
|
||||
return result_dict
|
||||
return response
|
||||
|
||||
# Dacă include_sparklines este False, calculăm doar indicatorii curenți
|
||||
@@ -537,6 +562,12 @@ async def get_financial_indicators(
|
||||
altman_task = FinancialIndicatorsService.calculate_altman_zscore(
|
||||
company, resolved_luna, resolved_an
|
||||
)
|
||||
profitabilitate_task = FinancialIndicatorsService.calculate_profitability_indicators(
|
||||
company, resolved_luna, resolved_an
|
||||
)
|
||||
solvabilitate_task = FinancialIndicatorsService.calculate_solvability_indicators(
|
||||
company, resolved_luna, resolved_an
|
||||
)
|
||||
|
||||
# Executăm toate calculele în paralel pentru performanță
|
||||
(
|
||||
@@ -545,14 +576,18 @@ async def get_financial_indicators(
|
||||
risc,
|
||||
cash_flow,
|
||||
dinamica,
|
||||
altman_zscore
|
||||
altman_zscore,
|
||||
profitabilitate,
|
||||
solvabilitate
|
||||
) = await asyncio.gather(
|
||||
lichiditate_task,
|
||||
eficienta_task,
|
||||
risc_task,
|
||||
cash_flow_task,
|
||||
dinamica_task,
|
||||
altman_task
|
||||
altman_task,
|
||||
profitabilitate_task,
|
||||
solvabilitate_task
|
||||
)
|
||||
|
||||
# Construim răspunsul
|
||||
@@ -562,7 +597,9 @@ async def get_financial_indicators(
|
||||
risc=risc,
|
||||
cash_flow=cash_flow,
|
||||
dinamica=dinamica,
|
||||
altman_zscore=altman_zscore
|
||||
altman_zscore=altman_zscore,
|
||||
profitabilitate=profitabilitate,
|
||||
solvabilitate=solvabilitate
|
||||
)
|
||||
|
||||
logger.info(
|
||||
@@ -570,6 +607,14 @@ async def get_financial_indicators(
|
||||
f"Z-Score={altman_zscore.zscore.value} ({altman_zscore.zscore.status})"
|
||||
)
|
||||
|
||||
# Add cache metadata if requested (for Telegram Bot / Dashboard)
|
||||
include_metadata = request.headers.get('X-Include-Cache-Metadata', '').lower() == 'true'
|
||||
if include_metadata:
|
||||
result_dict = response.dict() if hasattr(response, 'dict') else response
|
||||
result_dict['cache_hit'] = getattr(request.state, 'cache_hit', False)
|
||||
result_dict['response_time_ms'] = getattr(request.state, 'response_time_ms', 0)
|
||||
result_dict['cache_source'] = getattr(request.state, 'cache_source', None)
|
||||
return result_dict
|
||||
return response
|
||||
|
||||
except ValueError as e:
|
||||
|
||||
@@ -1546,14 +1546,16 @@ class DashboardService:
|
||||
raise
|
||||
|
||||
@staticmethod
|
||||
async def get_monthly_flows(company: int, luna: Optional[int] = None, an: Optional[int] = None) -> Dict[str, Any]:
|
||||
@cached(cache_type='monthly_flows', key_params=['company', 'luna', 'an'])
|
||||
async def get_monthly_flows(company: int, luna: Optional[int] = None, an: Optional[int] = None, request: Optional[Request] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Obține fluxurile lunare de intrare și ieșire pentru luna curentă
|
||||
Obține fluxurile lunare de intrare și ieșire pentru luna curentă (CACHED 30 min)
|
||||
|
||||
Args:
|
||||
company: ID-ul firmei
|
||||
luna: Luna contabilă (1-12), opțional
|
||||
an: Anul contabil, opțional
|
||||
request: Request object pentru cache metadata
|
||||
"""
|
||||
try:
|
||||
async with oracle_pool.get_connection() as connection:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user