""" Ticket Form Intake Platform - FastAPI Backend """ from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from contextlib import asynccontextmanager import logging from .config import settings from .services.database import db from .services.redis_service import redis_service from .services.rabbitmq_service import rabbitmq_service from .services.policy_service import policy_service from .services.s3_service import s3_service from .api import sms, claims, policy, upload, draft, events, n8n_proxy # Настройка логирования logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """ Lifecycle events: startup and shutdown """ # STARTUP logger.info("🚀 Starting Ticket Form Intake Platform...") try: # Подключаем PostgreSQL await db.connect() except Exception as e: logger.warning(f"⚠️ PostgreSQL not available: {e}") try: # Подключаем Redis await redis_service.connect() except Exception as e: logger.warning(f"⚠️ Redis not available: {e}") try: # Подключаем RabbitMQ await rabbitmq_service.connect() except Exception as e: logger.warning(f"⚠️ RabbitMQ not available: {e}") try: # Подключаем MySQL (для проверки полисов) await policy_service.connect() except Exception as e: logger.warning(f"⚠️ MySQL Policy DB not available: {e}") try: # Подключаем S3 (для загрузки файлов) s3_service.connect() except Exception as e: logger.warning(f"⚠️ S3 storage not available: {e}") logger.info("✅ Ticket Form Intake Platform started successfully!") yield # SHUTDOWN logger.info("🛑 Shutting down Ticket Form Intake Platform...") await db.disconnect() await redis_service.disconnect() await rabbitmq_service.disconnect() await policy_service.close() logger.info("👋 Ticket Form Intake Platform stopped") # Создаём FastAPI приложение app = FastAPI( title="Ticket Form Intake API", description="API для обработки обращений Ticket Form", version="1.0.0", lifespan=lifespan ) # CORS app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # API Routes app.include_router(sms.router) app.include_router(claims.router) app.include_router(policy.router) app.include_router(upload.router) app.include_router(draft.router) app.include_router(events.router) app.include_router(n8n_proxy.router) # 🔒 Безопасный proxy к n8n webhooks @app.get("/") async def root(): """Главная страница API""" return { "message": "🚀 Ticket Form Intake API", "version": "1.0.0", "status": "running", "docs": f"{settings.backend_url}/docs" } @app.get("/health") async def health(): """Health check - проверка всех сервисов""" health_status = { "status": "ok", "message": "API работает!", "services": {} } # Проверка PostgreSQL try: pg_healthy = await db.health_check() health_status["services"]["postgresql"] = { "status": "✅ healthy" if pg_healthy else "❌ unhealthy", "connected": pg_healthy } except: health_status["services"]["postgresql"] = { "status": "❌ unavailable", "connected": False } # Проверка Redis try: redis_healthy = await redis_service.health_check() health_status["services"]["redis"] = { "status": "✅ healthy" if redis_healthy else "❌ unhealthy", "connected": redis_healthy } except: health_status["services"]["redis"] = { "status": "❌ unavailable", "connected": False } # Проверка RabbitMQ try: rabbitmq_healthy = await rabbitmq_service.health_check() health_status["services"]["rabbitmq"] = { "status": "✅ healthy" if rabbitmq_healthy else "❌ unhealthy", "connected": rabbitmq_healthy } except: health_status["services"]["rabbitmq"] = { "status": "❌ unavailable", "connected": False } # Общий статус all_healthy = all( service.get("connected", False) for service in health_status["services"].values() ) if not all_healthy: health_status["status"] = "degraded" health_status["message"] = "⚠️ Некоторые сервисы недоступны" return health_status @app.get("/api/v1/test") async def test(): """Тестовый endpoint""" return { "success": True, "message": "✅ Backend API работает!", "services": { "redis": f"{settings.redis_host}:{settings.redis_port}", "postgres": f"{settings.postgres_host}:{settings.postgres_port}", "ocr": settings.ocr_api_url, "rabbitmq": f"{settings.rabbitmq_host}:{settings.rabbitmq_port}" } } @app.get("/api/v1/utils/client-ip") async def get_client_ip(request: Request): """Возвращает IP-адрес клиента по HTTP-запросу""" client_host = request.client.host if request.client else None return { "ip": client_host } @app.get("/api/v1/info") async def info(): """Информация о платформе""" return { "platform": settings.app_name, "version": "1.0.0", "tech_stack": { "backend": "Python FastAPI", "frontend": "React TypeScript", "database": "PostgreSQL + MySQL", "cache": "Redis", "queue": "RabbitMQ", "storage": "S3 Timeweb" }, "features": [ "OCR документов", "AI автозаполнение", "Проверка статуса выплат", "СБП выплаты", "Интеграция с CRM Vtiger" ] } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8200)