""" POS Integration Service Handles integration with external POS systems (Square, Toast, Lightspeed) """ from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse import structlog import time from contextlib import asynccontextmanager from app.core.config import settings from app.api import pos_config, webhooks, sync from app.core.database import init_db, close_db from shared.monitoring.health import router as health_router from shared.monitoring.logging import setup_logging # Setup logging setup_logging(service_name="pos-service") logger = structlog.get_logger() @asynccontextmanager async def lifespan(app: FastAPI): """Lifecycle management for FastAPI app""" logger.info("Starting POS Integration Service") # Startup try: # Initialize database connection logger.info("Initializing database connection") await init_db() # Add any startup logic here logger.info("POS Integration Service started successfully") yield except Exception as e: logger.error("Failed to start POS Integration Service", error=str(e)) raise finally: # Shutdown logger.info("Shutting down POS Integration Service") await close_db() # Create FastAPI app app = FastAPI( title="POS Integration Service", description="Handles integration with external POS systems", version="1.0.0", docs_url="/docs" if settings.ENVIRONMENT != "production" else None, redoc_url="/redoc" if settings.ENVIRONMENT != "production" else None, lifespan=lifespan ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Middleware for request logging and timing @app.middleware("http") async def log_requests(request: Request, call_next): start_time = time.time() # Log request logger.info( "Incoming request", method=request.method, url=str(request.url), client_ip=request.client.host if request.client else None ) response = await call_next(request) # Log response process_time = time.time() - start_time logger.info( "Request completed", method=request.method, url=str(request.url), status_code=response.status_code, process_time=f"{process_time:.4f}s" ) response.headers["X-Process-Time"] = str(process_time) return response # Global exception handler @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): logger.error( "Unhandled exception", error=str(exc), method=request.method, url=str(request.url) ) return JSONResponse( status_code=500, content={"detail": "Internal server error"} ) # Include routers app.include_router(health_router, prefix="/health", tags=["health"]) app.include_router(pos_config.router, prefix="/api/v1", tags=["pos-config"]) app.include_router(webhooks.router, prefix="/api/v1", tags=["webhooks"]) app.include_router(sync.router, prefix="/api/v1", tags=["sync"]) @app.get("/") async def root(): """Root endpoint""" return { "service": "POS Integration Service", "version": "1.0.0", "status": "running", "supported_pos_systems": ["square", "toast", "lightspeed"] } if __name__ == "__main__": import uvicorn uvicorn.run( "main:app", host="0.0.0.0", port=8000, reload=True )