bmc_hub/main.py

182 lines
6.5 KiB
Python
Raw Normal View History

2025-12-05 14:22:39 +01:00
"""
BMC Hub - FastAPI Application
Main application entry point
"""
import logging
from pathlib import Path
2025-12-05 14:22:39 +01:00
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import RedirectResponse
2025-12-05 14:22:39 +01:00
from contextlib import asynccontextmanager
from app.core.config import settings
from app.core.database import init_db
def get_version():
"""Read version from VERSION file"""
try:
version_file = Path(__file__).parent / "VERSION"
return version_file.read_text().strip()
except Exception:
return "unknown"
# Import Feature Routers
from app.customers.backend import router as customers_api
from app.customers.backend import views as customers_views
from app.customers.backend import bmc_office_router
from app.hardware.backend import router as hardware_api
from app.billing.backend import router as billing_api
from app.billing.frontend import views as billing_views
from app.system.backend import router as system_api
from app.system.backend import sync_router
from app.dashboard.backend import views as dashboard_views
from app.prepaid.backend import router as prepaid_api
from app.prepaid.backend import views as prepaid_views
from app.ticket.backend import router as ticket_api
from app.ticket.frontend import views as ticket_views
from app.vendors.backend import router as vendors_api
from app.vendors.backend import views as vendors_views
from app.timetracking.backend import router as timetracking_api
from app.timetracking.frontend import views as timetracking_views
from app.contacts.backend import views as contacts_views
from app.contacts.backend import router_simple as contacts_api
from app.tags.backend import router as tags_api
from app.tags.backend import views as tags_views
from app.emails.backend import router as emails_api
from app.emails.frontend import views as emails_views
from app.settings.backend import router as settings_api
from app.settings.backend import views as settings_views
from app.backups.backend.router import router as backups_api
from app.backups.frontend import views as backups_views
from app.backups.backend.scheduler import backup_scheduler
2025-12-05 14:22:39 +01:00
# 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()
# Start unified scheduler (handles backups + email fetch)
backup_scheduler.start()
2025-12-05 14:22:39 +01:00
logger.info("✅ System initialized successfully")
yield
# Shutdown
backup_scheduler.stop()
2025-12-05 14:22:39 +01:00
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 - use CORS_ORIGINS if set, otherwise fallback to ALLOWED_ORIGINS
cors_origins = settings.CORS_ORIGINS.split(",") if settings.CORS_ORIGINS else settings.ALLOWED_ORIGINS
2025-12-05 14:22:39 +01:00
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
2025-12-05 14:22:39 +01:00
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(customers_api.router, prefix="/api/v1", tags=["Customers"])
app.include_router(bmc_office_router.router, prefix="/api/v1", tags=["BMC Office"])
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(sync_router.router, prefix="/api/v1/system", tags=["System Sync"])
app.include_router(prepaid_api.router, prefix="/api/v1", tags=["Prepaid Cards"])
app.include_router(ticket_api.router, prefix="/api/v1/ticket", tags=["Tickets"])
app.include_router(vendors_api.router, prefix="/api/v1", tags=["Vendors"])
app.include_router(contacts_api.router, prefix="/api/v1", tags=["Contacts"])
app.include_router(timetracking_api, prefix="/api/v1", tags=["Time Tracking"])
app.include_router(tags_api.router, prefix="/api/v1", tags=["Tags"])
app.include_router(emails_api.router, prefix="/api/v1", tags=["Emails"])
app.include_router(settings_api.router, prefix="/api/v1", tags=["Settings"])
app.include_router(backups_api, prefix="/api/v1", tags=["Backups"])
# Frontend Routers
app.include_router(dashboard_views.router, tags=["Frontend"])
app.include_router(customers_views.router, tags=["Frontend"])
app.include_router(prepaid_views.router, tags=["Frontend"])
app.include_router(vendors_views.router, tags=["Frontend"])
app.include_router(timetracking_views.router, tags=["Frontend"])
app.include_router(billing_views.router, tags=["Frontend"])
app.include_router(ticket_views.router, prefix="/ticket", tags=["Frontend"])
app.include_router(contacts_views.router, tags=["Frontend"])
app.include_router(tags_views.router, tags=["Frontend"])
app.include_router(settings_views.router, tags=["Frontend"])
app.include_router(emails_views.router, tags=["Frontend"])
app.include_router(backups_views.router, tags=["Frontend"])
2025-12-05 14:22:39 +01:00
# 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": get_version()
2025-12-05 14:22:39 +01:00
}
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/*"],
2025-12-05 14:22:39 +01:00
log_level="info"
)
else:
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=False
)