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>
178 lines
6.5 KiB
Python
178 lines
6.5 KiB
Python
"""
|
|
Unified Configuration for ROA2WEB Backend
|
|
Consolidates settings from Reports, Data Entry, and Telegram modules
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import List
|
|
from pydantic_settings import BaseSettings
|
|
from functools import lru_cache
|
|
|
|
|
|
class UnifiedSettings(BaseSettings):
|
|
"""Unified application settings for all modules."""
|
|
|
|
# ============================================================================
|
|
# GENERAL APPLICATION SETTINGS
|
|
# ============================================================================
|
|
app_name: str = "ROA2WEB Unified Backend"
|
|
app_version: str = "1.0.0"
|
|
debug: bool = False
|
|
api_host: str = "0.0.0.0"
|
|
api_port: int = 8000
|
|
|
|
# ============================================================================
|
|
# ORACLE DATABASE (Shared by all modules)
|
|
# ============================================================================
|
|
oracle_user: str = ""
|
|
oracle_password: str = ""
|
|
oracle_host: str = "localhost"
|
|
oracle_port: int = 1526
|
|
oracle_sid: str = "ROA"
|
|
|
|
# ============================================================================
|
|
# JWT AUTHENTICATION (Shared by all modules)
|
|
# ============================================================================
|
|
jwt_secret_key: str = "change-me-in-production"
|
|
jwt_algorithm: str = "HS256"
|
|
access_token_expire_minutes: int = 30
|
|
refresh_token_expire_days: int = 7
|
|
|
|
# ============================================================================
|
|
# SESSION SECURITY - EMAIL 2FA (Telegram module)
|
|
# ============================================================================
|
|
auth_session_secret: str = "change-me-in-production"
|
|
|
|
# ============================================================================
|
|
# CORS
|
|
# ============================================================================
|
|
cors_origins: str = "http://localhost:3000,http://localhost:5173"
|
|
|
|
# ============================================================================
|
|
# REPORTS MODULE - CACHE CONFIGURATION
|
|
# ============================================================================
|
|
reports_cache_enabled: bool = True
|
|
reports_cache_type: str = "hybrid"
|
|
reports_cache_sqlite_path: str = "./data/cache/roa2web_cache.db"
|
|
reports_cache_memory_max_size: int = 1000
|
|
reports_cache_default_ttl: int = 900
|
|
|
|
# Cache TTL per type (seconds)
|
|
reports_cache_ttl_schema: int = 86400
|
|
reports_cache_ttl_companies: int = 1800
|
|
reports_cache_ttl_dashboard_summary: int = 1800
|
|
reports_cache_ttl_dashboard_trends: int = 1800
|
|
reports_cache_ttl_invoices: int = 600
|
|
reports_cache_ttl_invoices_summary: int = 900
|
|
reports_cache_ttl_treasury: int = 600
|
|
|
|
# Cache maintenance
|
|
reports_cache_cleanup_interval: int = 3600
|
|
reports_cache_auto_invalidate: bool = False
|
|
reports_cache_check_interval: int = 300
|
|
reports_cache_track_performance: bool = True
|
|
reports_cache_benchmark_on_startup: bool = False
|
|
|
|
# ============================================================================
|
|
# DATA ENTRY MODULE - CONFIGURATION
|
|
# ============================================================================
|
|
data_entry_sqlite_database_path: str = "data/receipts/receipts.db"
|
|
data_entry_upload_path: str = "data/receipts/uploads"
|
|
data_entry_max_upload_size_mb: int = 10
|
|
data_entry_allowed_mime_types: List[str] = [
|
|
"image/jpeg",
|
|
"image/png",
|
|
"image/gif",
|
|
"image/webp",
|
|
"application/pdf",
|
|
]
|
|
|
|
# ============================================================================
|
|
# TELEGRAM MODULE - BOT CONFIGURATION
|
|
# ============================================================================
|
|
telegram_bot_token: str = ""
|
|
telegram_smtp_host: str = ""
|
|
telegram_smtp_port: int = 587
|
|
telegram_smtp_user: str = ""
|
|
telegram_smtp_password: str = ""
|
|
telegram_smtp_from_email: str = ""
|
|
telegram_smtp_from_name: str = "ROA2WEB"
|
|
telegram_smtp_use_tls: bool = True
|
|
telegram_email_max_retries: int = 3
|
|
telegram_email_retry_delay: float = 2.0
|
|
telegram_sqlite_database_path: str = "data/telegram/telegram.db"
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
extra = "ignore"
|
|
case_sensitive = False
|
|
|
|
# ============================================================================
|
|
# COMPUTED PROPERTIES
|
|
# ============================================================================
|
|
|
|
@property
|
|
def oracle_dsn(self) -> str:
|
|
"""Get Oracle DSN string."""
|
|
return f"{self.oracle_host}:{self.oracle_port}/{self.oracle_sid}"
|
|
|
|
@property
|
|
def cors_origins_list(self) -> List[str]:
|
|
"""Get CORS origins as list."""
|
|
return [origin.strip() for origin in self.cors_origins.split(",")]
|
|
|
|
# Data Entry properties
|
|
@property
|
|
def data_entry_database_url(self) -> str:
|
|
"""Get SQLite database URL for async (Data Entry)."""
|
|
# Resolve to absolute path for Windows/IIS compatibility
|
|
abs_path = Path(self.data_entry_sqlite_database_path).resolve()
|
|
return f"sqlite+aiosqlite:///{abs_path}"
|
|
|
|
@property
|
|
def data_entry_sync_database_url(self) -> str:
|
|
"""Get SQLite database URL for sync operations (Alembic)."""
|
|
# Resolve to absolute path for Windows/IIS compatibility
|
|
abs_path = Path(self.data_entry_sqlite_database_path).resolve()
|
|
return f"sqlite:///{abs_path}"
|
|
|
|
@property
|
|
def data_entry_upload_path_resolved(self) -> Path:
|
|
"""Get resolved upload path."""
|
|
path = Path(self.data_entry_upload_path)
|
|
path.mkdir(parents=True, exist_ok=True)
|
|
return path
|
|
|
|
@property
|
|
def data_entry_max_upload_size_bytes(self) -> int:
|
|
"""Get max upload size in bytes."""
|
|
return self.data_entry_max_upload_size_mb * 1024 * 1024
|
|
|
|
# Reports cache properties
|
|
@property
|
|
def reports_cache_sqlite_path_resolved(self) -> Path:
|
|
"""Get resolved cache SQLite path."""
|
|
path = Path(self.reports_cache_sqlite_path)
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
return path
|
|
|
|
# Telegram properties
|
|
@property
|
|
def telegram_sqlite_path_resolved(self) -> Path:
|
|
"""Get resolved Telegram SQLite path."""
|
|
path = Path(self.telegram_sqlite_database_path)
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
return path
|
|
|
|
|
|
@lru_cache()
|
|
def get_settings() -> UnifiedSettings:
|
|
"""Get cached settings instance."""
|
|
return UnifiedSettings()
|
|
|
|
|
|
# Convenience instance
|
|
settings = get_settings()
|