"""FastAPI application entry point for Data Entry App.""" import sys import logging import threading from pathlib import Path from contextlib import asynccontextmanager # Load .env file BEFORE any imports that use os.getenv() from dotenv import load_dotenv load_dotenv() from fastapi import FastAPI # Configure logging to show INFO level messages logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%H:%M:%S' ) from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles # Add shared modules to path project_root = Path(__file__).parent.parent.parent.parent sys.path.insert(0, str(project_root / "shared")) from app.config import settings from app.db.database import init_db # Import Oracle pool for auth service from database.oracle_pool import oracle_pool @asynccontextmanager async def lifespan(app: FastAPI): """Application lifespan - startup and shutdown events.""" # Startup print(f"Starting {settings.app_name} v{settings.app_version}") # Initialize Oracle pool (required for authentication) try: await oracle_pool.initialize() print("Oracle pool initialized") except Exception as e: print(f"Warning: Oracle pool initialization failed: {e}") print("Authentication will not work without Oracle connection") # Initialize SQLite database await init_db() print("Database initialized") # Ensure upload directory exists settings.upload_path_resolved print(f"Upload path: {settings.upload_path_resolved}") # Pre-initialize OCR engine in background (PaddleOCR takes 15-20s) def init_ocr_background(): try: from app.services.ocr_service import ocr_service ocr_service.ocr_engine._init_paddle_lazy() print("OCR engine ready") except Exception as e: print(f"Warning: OCR engine pre-load failed: {e}") print("Starting OCR engine pre-load (background)...") threading.Thread(target=init_ocr_background, daemon=True).start() yield # Shutdown print("Shutting down...") try: await oracle_pool.close() print("Oracle pool closed") except Exception as e: print(f"Warning: Oracle pool close failed: {e}") # Create FastAPI app app = FastAPI( title=settings.app_name, version=settings.app_version, description="API pentru introducere bonuri fiscale cu workflow de aprobare", lifespan=lifespan, ) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Authentication middleware from auth.middleware import AuthenticationMiddleware app.add_middleware( AuthenticationMiddleware, excluded_paths=["/docs", "/redoc", "/openapi.json", "/health", "/", "/api/auth/login", "/api/auth/refresh"] ) # Mount static files for uploads (optional - can serve through nginx in prod) uploads_path = Path(settings.upload_path) if uploads_path.exists(): app.mount("/uploads", StaticFiles(directory=str(uploads_path)), name="uploads") # Health check endpoint @app.get("/health") async def health_check(): """Health check endpoint.""" return { "status": "healthy", "app": settings.app_name, "version": settings.app_version, } # Import and include routers from app.routers import receipts, ocr, nomenclature app.include_router(receipts.router, prefix="/api/receipts", tags=["receipts"]) app.include_router(ocr.router, prefix="/api/ocr", tags=["ocr"]) app.include_router(nomenclature.router, prefix="/api/nomenclature", tags=["nomenclature"]) # Auth router from auth.routes import create_auth_router auth_router = create_auth_router(prefix="") # No prefix - we set it in include_router app.include_router(auth_router, prefix="/api/auth", tags=["auth"]) # Root endpoint @app.get("/") async def root(): """Root endpoint - API information.""" return { "name": settings.app_name, "version": settings.app_version, "docs": "/docs", "health": "/health", }