🚀 MVP: FastAPI + React форма с SMS верификацией

 Инфраструктура: PostgreSQL, Redis, RabbitMQ, S3
 Backend: SMS сервис + API endpoints
 Frontend: React форма (3 шага) + SMS верификация
This commit is contained in:
AI Assistant
2025-10-24 16:19:58 +03:00
parent 8af23e90fa
commit 0f82eef08d
42 changed files with 2902 additions and 241 deletions

View File

@@ -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)