# ================================================================ # services/orders/app/main.py # ================================================================ """ Orders Service - FastAPI Application Customer orders and procurement planning service """ from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager import structlog from app.core.config import settings from app.core.database import init_database, get_db_health from app.api.orders import router as orders_router from app.api.procurement import router as procurement_router from app.services.procurement_scheduler_service import ProcurementSchedulerService # Configure logging logger = structlog.get_logger() @asynccontextmanager async def lifespan(app: FastAPI): """Manage application lifespan events""" # Startup try: await init_database() logger.info("Database initialized successfully") # Initialize procurement scheduler service scheduler_service = ProcurementSchedulerService(settings) await scheduler_service.start() logger.info("Procurement scheduler service started") # Store scheduler service in app state app.state.scheduler_service = scheduler_service logger.info("Orders service started successfully") except Exception as e: logger.error("Failed to initialize orders service", error=str(e)) raise yield # Shutdown logger.info("Orders service shutting down") try: # Stop scheduler service if hasattr(app.state, 'scheduler_service'): await app.state.scheduler_service.stop() logger.info("Scheduler service stopped") except Exception as e: logger.error("Error stopping scheduler service", error=str(e)) # Create FastAPI application app = FastAPI( title=settings.APP_NAME, description=settings.DESCRIPTION, version=settings.VERSION, lifespan=lifespan ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # Configure based on environment allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(orders_router, prefix="/api/v1") app.include_router(procurement_router, prefix="/api/v1") @app.get("/health") async def health_check(): """Health check endpoint""" try: db_healthy = await get_db_health() health_status = { "status": "healthy" if db_healthy else "unhealthy", "service": settings.SERVICE_NAME, "version": settings.VERSION, "database": "connected" if db_healthy else "disconnected" } if not db_healthy: health_status["status"] = "unhealthy" return health_status except Exception as e: logger.error("Health check failed", error=str(e)) return { "status": "unhealthy", "service": settings.SERVICE_NAME, "version": settings.VERSION, "error": str(e) } @app.get("/") async def root(): """Root endpoint""" return { "service": settings.APP_NAME, "version": settings.VERSION, "description": settings.DESCRIPTION, "status": "running" } @app.post("/test/procurement-scheduler") async def test_procurement_scheduler(): """Test endpoint to manually trigger procurement scheduler""" try: if hasattr(app.state, 'scheduler_service'): scheduler_service = app.state.scheduler_service await scheduler_service.test_procurement_generation() return {"message": "Procurement scheduler test triggered successfully"} else: return {"error": "Scheduler service not available"} except Exception as e: logger.error("Error testing procurement scheduler", error=str(e)) return {"error": f"Failed to trigger scheduler test: {str(e)}"} @app.middleware("http") async def logging_middleware(request: Request, call_next): """Add request logging middleware""" import time start_time = time.time() response = await call_next(request) process_time = time.time() - start_time logger.info("HTTP request processed", method=request.method, url=str(request.url), status_code=response.status_code, process_time=round(process_time, 4)) return response if __name__ == "__main__": import uvicorn uvicorn.run( "main:app", host="0.0.0.0", port=8000, reload=settings.DEBUG )