""" 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).""" return f"sqlite+aiosqlite:///{self.data_entry_sqlite_database_path}" @property def data_entry_sync_database_url(self) -> str: """Get SQLite database URL for sync operations (Alembic).""" return f"sqlite:///{self.data_entry_sqlite_database_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()