🚀 MVP: FastAPI + React форма с SMS верификацией
✅ Инфраструктура: PostgreSQL, Redis, RabbitMQ, S3 ✅ Backend: SMS сервис + API endpoints ✅ Frontend: React форма (3 шага) + SMS верификация
This commit is contained in:
@@ -3,33 +3,84 @@ ERV Insurance Platform - FastAPI Backend
|
||||
"""
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
from app.config import settings
|
||||
import redis
|
||||
import asyncpg
|
||||
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 .api import sms, claims
|
||||
|
||||
# Настройка логирования
|
||||
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 ERV 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}")
|
||||
|
||||
logger.info("✅ ERV Platform started successfully!")
|
||||
|
||||
yield
|
||||
|
||||
# SHUTDOWN
|
||||
logger.info("🛑 Shutting down ERV Platform...")
|
||||
|
||||
await db.disconnect()
|
||||
await redis_service.disconnect()
|
||||
await rabbitmq_service.disconnect()
|
||||
|
||||
logger.info("👋 ERV Platform stopped")
|
||||
|
||||
|
||||
# Создаём FastAPI приложение
|
||||
app = FastAPI(
|
||||
title="ERV Insurance Platform API",
|
||||
description="API для обработки страховых обращений с OCR, AI и интеграциями",
|
||||
description="API для обработки страховых обращений",
|
||||
version="1.0.0",
|
||||
docs_url="/docs",
|
||||
redoc_url="/redoc"
|
||||
lifespan=lifespan
|
||||
)
|
||||
|
||||
# CORS middleware
|
||||
# CORS
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=settings.cors_origins,
|
||||
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)
|
||||
|
||||
# ============================================
|
||||
# HEALTH CHECKS
|
||||
# ============================================
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
@@ -37,140 +88,111 @@ async def root():
|
||||
return {
|
||||
"message": "🚀 ERV Insurance Platform API",
|
||||
"version": "1.0.0",
|
||||
"docs": f"{settings.backend_url}/docs",
|
||||
"status": "running"
|
||||
"status": "running",
|
||||
"docs": "http://147.45.146.17:8100/docs"
|
||||
}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health_check():
|
||||
"""Проверка здоровья сервисов"""
|
||||
async def health():
|
||||
"""Health check - проверка всех сервисов"""
|
||||
health_status = {
|
||||
"api": "ok",
|
||||
"redis": "checking",
|
||||
"postgres": "checking",
|
||||
"ocr": "checking"
|
||||
"status": "ok",
|
||||
"message": "API работает!",
|
||||
"services": {}
|
||||
}
|
||||
|
||||
# Проверка Redis
|
||||
try:
|
||||
r = redis.Redis(
|
||||
host=settings.redis_host,
|
||||
port=settings.redis_port,
|
||||
password=settings.redis_password,
|
||||
decode_responses=True
|
||||
)
|
||||
r.ping()
|
||||
health_status["redis"] = "ok"
|
||||
except Exception as e:
|
||||
health_status["redis"] = f"error: {str(e)}"
|
||||
|
||||
# Проверка PostgreSQL
|
||||
try:
|
||||
conn = await asyncpg.connect(
|
||||
host=settings.postgres_host,
|
||||
port=settings.postgres_port,
|
||||
database=settings.postgres_db,
|
||||
user=settings.postgres_user,
|
||||
password=settings.postgres_password
|
||||
)
|
||||
await conn.execute("SELECT 1")
|
||||
await conn.close()
|
||||
health_status["postgres"] = "ok"
|
||||
except Exception as e:
|
||||
health_status["postgres"] = f"error: {str(e)}"
|
||||
|
||||
# Проверка OCR
|
||||
import httpx
|
||||
try:
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(f"{settings.ocr_api_url}/", timeout=5.0)
|
||||
health_status["ocr"] = "ok" if response.status_code in [200, 404] else "unreachable"
|
||||
except Exception as e:
|
||||
health_status["ocr"] = f"error: {str(e)}"
|
||||
|
||||
all_ok = all(v == "ok" for v in health_status.values())
|
||||
|
||||
return JSONResponse(
|
||||
status_code=200 if all_ok else 503,
|
||||
content={
|
||||
"status": "healthy" if all_ok else "degraded",
|
||||
"services": health_status
|
||||
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
|
||||
|
||||
|
||||
# ============================================
|
||||
# API V1 ENDPOINTS
|
||||
# ============================================
|
||||
|
||||
@app.get("/api/v1/test")
|
||||
async def test_endpoint():
|
||||
async def test():
|
||||
"""Тестовый endpoint"""
|
||||
return {
|
||||
"message": "✅ API работает!",
|
||||
"env": settings.app_env,
|
||||
"debug": settings.debug,
|
||||
"success": True,
|
||||
"message": "✅ Backend API работает!",
|
||||
"services": {
|
||||
"redis": f"{settings.redis_host}:{settings.redis_port}",
|
||||
"postgres": f"{settings.postgres_host}:{settings.postgres_port}",
|
||||
"rabbitmq": f"{settings.rabbitmq_host}:{settings.rabbitmq_port}",
|
||||
"ocr": settings.ocr_api_url
|
||||
"redis": "localhost:6379",
|
||||
"postgres": "147.45.189.234:5432",
|
||||
"ocr": "147.45.146.17:8001",
|
||||
"rabbitmq": "185.197.75.249:5672"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/v1/info")
|
||||
async def get_info():
|
||||
async def info():
|
||||
"""Информация о платформе"""
|
||||
return {
|
||||
"platform": "ERV Insurance Claims",
|
||||
"version": "1.0.0",
|
||||
"features": [
|
||||
"OCR документов (паспорт, билеты)",
|
||||
"AI автозаполнение (Gemini Vision)",
|
||||
"Проверка рейсов (FlightAware)",
|
||||
"СБП выплаты",
|
||||
"Интеграция с CRM"
|
||||
],
|
||||
"tech_stack": {
|
||||
"backend": "Python FastAPI",
|
||||
"frontend": "React TypeScript",
|
||||
"database": "PostgreSQL + MySQL",
|
||||
"cache": "Redis",
|
||||
"queue": "RabbitMQ",
|
||||
"storage": "S3 Timeweb",
|
||||
"ocr": "Internal Service",
|
||||
"ai": "OpenRouter Gemini 2.0"
|
||||
}
|
||||
"storage": "S3 Timeweb"
|
||||
},
|
||||
"features": [
|
||||
"OCR документов (паспорт, билеты)",
|
||||
"AI автозаполнение (Gemini Vision)",
|
||||
"Проверка рейсов (FlightAware)",
|
||||
"СБП выплаты",
|
||||
"Интеграция с CRM Vtiger"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
# ============================================
|
||||
# STARTUP/SHUTDOWN
|
||||
# ============================================
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""При старте приложения"""
|
||||
print("🚀 ERV Insurance Platform запускается...")
|
||||
print(f"📍 Backend URL: {settings.backend_url}")
|
||||
print(f"📍 API Docs: {settings.backend_url}/docs")
|
||||
print(f"🔗 Frontend URL: {settings.frontend_url}")
|
||||
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
"""При остановке приложения"""
|
||||
print("👋 ERV Insurance Platform остановлен")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import uvicorn
|
||||
uvicorn.run(
|
||||
"main:app",
|
||||
host="0.0.0.0",
|
||||
port=8100,
|
||||
reload=True
|
||||
)
|
||||
|
||||
uvicorn.run(app, host="0.0.0.0", port=8100)
|
||||
|
||||
Reference in New Issue
Block a user