""" BMC Hub - FastAPI Application Main application entry point """ import logging from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles from fastapi.responses import RedirectResponse from contextlib import asynccontextmanager from app.core.config import settings from app.core.database import init_db # Import Feature Routers from app.auth.backend import router as auth_api from app.auth.backend import views as auth_views from app.customers.backend import router as customers_api from app.customers.backend import views as customers_views from app.contacts.backend import router as contacts_api from app.contacts.backend import views as contacts_views from app.vendors.backend import router as vendors_api from app.vendors.backend import views as vendors_views from app.settings.backend import router as settings_api from app.settings.backend import views as settings_views from app.hardware.backend import router as hardware_api from app.billing.backend import router as billing_api from app.system.backend import router as system_api from app.dashboard.backend import views as dashboard_views from app.dashboard.backend import router as dashboard_api # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.StreamHandler(), logging.FileHandler('logs/app.log') ] ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """Lifecycle management - startup and shutdown""" # Startup logger.info("🚀 Starting BMC Hub...") logger.info(f"Database: {settings.DATABASE_URL}") init_db() logger.info("✅ System initialized successfully") yield # Shutdown logger.info("👋 Shutting down...") # Create FastAPI app app = FastAPI( title="BMC Hub API", description=""" Central management system for BMC Networks. **Key Features:** - Customer management - Hardware tracking - Service management - Billing integration """, version="1.0.0", lifespan=lifespan, docs_url="/api/docs", redoc_url="/api/redoc", openapi_url="/api/openapi.json" ) # CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.ALLOWED_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(auth_api.router, prefix="/api/v1/auth", tags=["Authentication"]) app.include_router(customers_api.router, prefix="/api/v1", tags=["Customers"]) app.include_router(contacts_api.router, prefix="/api/v1", tags=["Contacts"]) app.include_router(vendors_api.router, prefix="/api/v1", tags=["Vendors"]) app.include_router(settings_api.router, prefix="/api/v1", tags=["Settings"]) app.include_router(hardware_api.router, prefix="/api/v1", tags=["Hardware"]) app.include_router(billing_api.router, prefix="/api/v1", tags=["Billing"]) app.include_router(system_api.router, prefix="/api/v1", tags=["System"]) app.include_router(dashboard_api.router, prefix="/api/v1/dashboard", tags=["Dashboard"]) # Frontend Routers app.include_router(auth_views.router, tags=["Frontend"]) app.include_router(dashboard_views.router, tags=["Frontend"]) app.include_router(customers_views.router, tags=["Frontend"]) app.include_router(contacts_views.router, tags=["Frontend"]) app.include_router(vendors_views.router, tags=["Frontend"]) app.include_router(settings_views.router, tags=["Frontend"]) # Serve static files (UI) app.mount("/static", StaticFiles(directory="static", html=True), name="static") @app.get("/health") async def health_check(): """Health check endpoint""" return { "status": "healthy", "service": "BMC Hub", "version": "1.0.0" } if __name__ == "__main__": import uvicorn import os # Only enable reload in local development (not in Docker) enable_reload = os.getenv("ENABLE_RELOAD", "false").lower() == "true" if enable_reload: uvicorn.run( "main:app", host="0.0.0.0", port=8000, reload=True, reload_includes=["*.py"], reload_dirs=["app"], reload_excludes=[".git/*", "*.pyc", "__pycache__/*", "logs/*", "uploads/*", "data/*"], log_level="info" ) else: uvicorn.run( "main:app", host="0.0.0.0", port=8000, reload=False )