- Добавлен сервис CrmMySQLService для подключения к MySQL БД vtiger CRM - Обновлён get_draft() для прямого SQL запроса к MySQL вместо webservice API - Получение cf_2624 и всех данных контакта из MySQL - Обновлена документация и SQL файлы для n8n - Добавлено логирование для отладки Преимущества: - Проще: один SQL запрос вместо цепочки HTTP запросов - Быстрее: прямой запрос к БД - Надёжнее: не зависит от webservice API - Актуальнее: всегда свежие данные из БД
241 lines
7.1 KiB
Python
241 lines
7.1 KiB
Python
"""
|
||
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.crm_mysql_service import crm_mysql_service
|
||
from .services.s3_service import s3_service
|
||
from .api import sms, claims, policy, upload, draft, events, n8n_proxy, session, documents
|
||
|
||
# Настройка логирования
|
||
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()
|
||
# Инициализируем session API с Redis connection
|
||
session.init_redis(redis_service.client)
|
||
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:
|
||
# Подключаем MySQL CRM (vtiger)
|
||
await crm_mysql_service.connect()
|
||
except Exception as e:
|
||
logger.warning(f"⚠️ MySQL CRM 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()
|
||
await crm_mysql_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.include_router(session.router) # 🔑 Session management через Redis
|
||
app.include_router(documents.router) # 📄 Documents upload and processing
|
||
|
||
|
||
@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)
|
||
|