bmc_hub/main.py
Christian d5dd958bf9 Refactor Sager module templates and functionality
- Updated index.html to extend base template and improve structure.
- Added new styles and search/filter functionality in the Sager list view.
- Created a backup of the old index.html as index_old.html.
- Updated navigation links in base.html for consistency.
- Included new dashboard API router in main.py.
- Added test scripts for customer and sag queries to validate database interactions.
2026-02-01 11:58:44 +01:00

216 lines
8.5 KiB
Python

"""
BMC Hub - FastAPI Application
Main application entry point
"""
import logging
from pathlib import Path
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
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 # Replaced by hardware module
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.dashboard.backend import router as dashboard_api
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
from app.conversations.backend import router as conversations_api
from app.conversations.frontend import views as conversations_views
from app.opportunities.backend import router as opportunities_api
from app.opportunities.frontend import views as opportunities_views
# Modules
from app.modules.webshop.backend import router as webshop_api
from app.modules.webshop.frontend import views as webshop_views
from app.modules.sag.backend import router as sag_api
from app.modules.sag.frontend import views as sag_views
from app.modules.hardware.backend import router as hardware_module_api
from app.modules.hardware.frontend import views as hardware_module_views
from app.modules.locations.backend import router as locations_api
from app.modules.locations.frontend import views as locations_views
# 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()
logger.info("✅ System initialized successfully")
yield
# Shutdown
backup_scheduler.stop()
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
app.add_middleware(
CORSMiddleware,
allow_origins=cors_origins,
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"]) # Replaced by hardware module
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", tags=["Dashboard"])
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"])
app.include_router(conversations_api.router, prefix="/api/v1", tags=["Conversations"])
app.include_router(opportunities_api.router, prefix="/api/v1", tags=["Opportunities"])
# Module Routers
app.include_router(webshop_api.router, prefix="/api/v1", tags=["Webshop"])
app.include_router(sag_api.router, prefix="/api/v1", tags=["Cases"])
app.include_router(hardware_module_api.router, prefix="/api/v1", tags=["Hardware Module"])
app.include_router(locations_api, prefix="/api/v1", tags=["Locations"])
# 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"])
app.include_router(conversations_views.router, tags=["Frontend"])
app.include_router(webshop_views.router, tags=["Frontend"])
app.include_router(opportunities_views.router, tags=["Frontend"])
app.include_router(sag_views.router, tags=["Frontend"])
app.include_router(hardware_module_views.router, tags=["Frontend"])
app.include_router(locations_views.router, tags=["Frontend"])
# Serve static files (UI)
app.mount("/static", StaticFiles(directory="static", html=True), name="static")
app.mount("/docs", StaticFiles(directory="docs"), name="docs")
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"service": "BMC Hub",
"version": get_version()
}
if __name__ == "__main__":
import uvicorn
import os
# Only enable reload in local development (not in Docker) - check both variables
enable_reload = (
os.getenv("ENABLE_RELOAD", "false").lower() == "true" or
os.getenv("API_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
)