2025-10-24 12:02:17 +03:00
|
|
|
|
# 🏗️ ERV Insurance Platform - Архитектура проекта
|
|
|
|
|
|
|
|
|
|
|
|
**Дата создания**: 24.10.2025
|
|
|
|
|
|
**Технологии**: Python FastAPI + React TypeScript
|
|
|
|
|
|
**Статус**: 🚧 В разработке
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 Обзор архитектуры
|
|
|
|
|
|
|
|
|
|
|
|
### **Технологический стек:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ Frontend Layer (React) │
|
|
|
|
|
|
│ ├─ React 18 + TypeScript │
|
|
|
|
|
|
│ ├─ Vite (сборка) │
|
|
|
|
|
|
│ ├─ Ant Design (UI компоненты) │
|
|
|
|
|
|
│ ├─ React Query (API кеш) │
|
|
|
|
|
|
│ ├─ Zustand (state) │
|
|
|
|
|
|
│ └─ WebSocket для real-time │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
│ REST API + WebSocket
|
|
|
|
|
|
▼
|
|
|
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
|
|
|
│ Backend Layer (Python FastAPI) │
|
|
|
|
|
|
│ ├─ FastAPI (асинхронный web framework) │
|
|
|
|
|
|
│ ├─ Pydantic (валидация данных) │
|
|
|
|
|
|
│ ├─ SQLAlchemy (PostgreSQL ORM) │
|
|
|
|
|
|
│ ├─ Redis (кеш, rate limiting) │
|
|
|
|
|
|
│ ├─ RabbitMQ (очереди задач) │
|
|
|
|
|
|
│ ├─ Celery (воркеры) │
|
|
|
|
|
|
│ └─ pytest (тесты) │
|
|
|
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
├─► PostgreSQL (147.45.189.234) - логи, данные
|
|
|
|
|
|
├─► Redis (localhost:6379) - кеш
|
|
|
|
|
|
├─► RabbitMQ (185.197.75.249) - очереди
|
|
|
|
|
|
├─► MySQL (localhost) - проверка полисов
|
|
|
|
|
|
├─► OCR Service (147.45.146.17:8001)
|
|
|
|
|
|
├─► OpenRouter AI (Gemini Vision)
|
|
|
|
|
|
├─► FlightAware API
|
|
|
|
|
|
└─► S3 Timeweb Cloud
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📁 Структура проекта
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
erv_platform/
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ backend/ ← Python FastAPI
|
|
|
|
|
|
│ ├─ app/
|
|
|
|
|
|
│ │ ├─ main.py ← Точка входа FastAPI
|
|
|
|
|
|
│ │ ├─ config.py ← Настройки из .env
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ api/ ← API endpoints
|
|
|
|
|
|
│ │ │ ├─ __init__.py
|
|
|
|
|
|
│ │ │ ├─ deps.py ← Зависимости (auth, db)
|
|
|
|
|
|
│ │ │ └─ endpoints/
|
|
|
|
|
|
│ │ │ ├─ documents.py ← OCR, Vision
|
|
|
|
|
|
│ │ │ ├─ flights.py ← Проверка рейсов
|
|
|
|
|
|
│ │ │ ├─ claims.py ← Создание обращений
|
|
|
|
|
|
│ │ │ ├─ policies.py ← Проверка полисов
|
|
|
|
|
|
│ │ │ └─ analytics.py ← Статистика
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ services/ ← Бизнес-логика
|
|
|
|
|
|
│ │ │ ├─ ocr_service.py
|
|
|
|
|
|
│ │ │ ├─ ai_service.py ← OpenRouter Vision
|
|
|
|
|
|
│ │ │ ├─ flight_service.py ← FlightAware
|
|
|
|
|
|
│ │ │ ├─ s3_service.py ← Timeweb S3
|
|
|
|
|
|
│ │ │ ├─ crm_service.py ← Интеграция с Vtiger
|
|
|
|
|
|
│ │ │ ├─ cache_service.py ← Redis
|
|
|
|
|
|
│ │ │ └─ queue_service.py ← RabbitMQ
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ models/ ← Pydantic модели
|
|
|
|
|
|
│ │ │ ├─ claim.py ← Обращение
|
|
|
|
|
|
│ │ │ ├─ document.py ← Документ
|
|
|
|
|
|
│ │ │ ├─ passport.py ← Паспорт
|
|
|
|
|
|
│ │ │ ├─ ticket.py ← Билет
|
|
|
|
|
|
│ │ │ └─ flight.py ← Рейс
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ db/ ← База данных
|
|
|
|
|
|
│ │ │ ├─ postgres.py ← PostgreSQL session
|
|
|
|
|
|
│ │ │ ├─ mysql.py ← MySQL session (полисы)
|
|
|
|
|
|
│ │ │ └─ models.py ← SQLAlchemy модели
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ workers/ ← RabbitMQ воркеры
|
|
|
|
|
|
│ │ │ ├─ ocr_worker.py
|
|
|
|
|
|
│ │ │ ├─ flight_worker.py
|
|
|
|
|
|
│ │ │ └─ notification_worker.py
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ core/ ← Утилиты
|
|
|
|
|
|
│ │ │ ├─ security.py ← Rate limiting
|
|
|
|
|
|
│ │ │ ├─ logger.py ← Логирование
|
|
|
|
|
|
│ │ │ └─ exceptions.py
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ └─ tests/ ← Тесты
|
|
|
|
|
|
│ │ ├─ test_api.py
|
|
|
|
|
|
│ │ └─ test_services.py
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├─ migrations/ ← SQL миграции
|
|
|
|
|
|
│ │ ├─ 001_create_logs.sql
|
|
|
|
|
|
│ │ ├─ 002_create_documents.sql
|
|
|
|
|
|
│ │ └─ 003_create_claims.sql
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├─ requirements.txt ← Python зависимости
|
|
|
|
|
|
│ ├─ .env.example
|
|
|
|
|
|
│ ├─ Dockerfile
|
|
|
|
|
|
│ └─ pyproject.toml
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ frontend/ ← React TypeScript
|
|
|
|
|
|
│ ├─ src/
|
|
|
|
|
|
│ │ ├─ App.tsx ← Главный компонент
|
|
|
|
|
|
│ │ ├─ main.tsx ← Точка входа
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ components/ ← UI компоненты
|
|
|
|
|
|
│ │ │ ├─ layout/
|
|
|
|
|
|
│ │ │ │ ├─ Header.tsx
|
|
|
|
|
|
│ │ │ │ └─ Footer.tsx
|
|
|
|
|
|
│ │ │ ├─ form/
|
|
|
|
|
|
│ │ │ │ ├─ FormWizard.tsx ← Многошаговая форма
|
|
|
|
|
|
│ │ │ │ ├─ StepPersonal.tsx ← Шаг 1
|
|
|
|
|
|
│ │ │ │ ├─ StepFlight.tsx ← Шаг 2
|
|
|
|
|
|
│ │ │ │ └─ StepDocuments.tsx ← Шаг 3
|
|
|
|
|
|
│ │ │ ├─ upload/
|
|
|
|
|
|
│ │ │ │ ├─ PassportUpload.tsx ← Загрузка паспорта + OCR
|
|
|
|
|
|
│ │ │ │ ├─ TicketUpload.tsx ← Загрузка билета + OCR
|
|
|
|
|
|
│ │ │ │ └─ DocumentUpload.tsx ← Общий компонент
|
|
|
|
|
|
│ │ │ ├─ flight/
|
|
|
|
|
|
│ │ │ │ ├─ FlightChecker.tsx ← Проверка рейса
|
|
|
|
|
|
│ │ │ │ └─ FlightStatus.tsx ← Показ статуса
|
|
|
|
|
|
│ │ │ └─ common/
|
|
|
|
|
|
│ │ │ ├─ Loading.tsx
|
|
|
|
|
|
│ │ │ ├─ ErrorBoundary.tsx
|
|
|
|
|
|
│ │ │ └─ Notification.tsx
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ pages/ ← Страницы
|
|
|
|
|
|
│ │ │ ├─ ClaimForm.tsx ← Главная форма
|
|
|
|
|
|
│ │ │ ├─ Success.tsx ← Успех
|
|
|
|
|
|
│ │ │ └─ Error.tsx ← Ошибка
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ api/ ← API клиент
|
|
|
|
|
|
│ │ │ ├─ client.ts ← Axios instance
|
|
|
|
|
|
│ │ │ ├─ documents.ts ← API документов
|
|
|
|
|
|
│ │ │ ├─ flights.ts ← API рейсов
|
|
|
|
|
|
│ │ │ └─ claims.ts ← API обращений
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ hooks/ ← React hooks
|
|
|
|
|
|
│ │ │ ├─ useOCR.ts
|
|
|
|
|
|
│ │ │ ├─ useFlightCheck.ts
|
|
|
|
|
|
│ │ │ └─ useWebSocket.ts
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ ├─ types/ ← TypeScript типы
|
|
|
|
|
|
│ │ │ ├─ claim.ts
|
|
|
|
|
|
│ │ │ ├─ document.ts
|
|
|
|
|
|
│ │ │ └─ flight.ts
|
|
|
|
|
|
│ │ │
|
|
|
|
|
|
│ │ └─ utils/ ← Утилиты
|
|
|
|
|
|
│ │ ├─ validators.ts
|
|
|
|
|
|
│ │ └─ formatters.ts
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├─ public/
|
|
|
|
|
|
│ │ ├─ index.html
|
|
|
|
|
|
│ │ └─ favicon.ico
|
|
|
|
|
|
│ │
|
|
|
|
|
|
│ ├─ package.json
|
|
|
|
|
|
│ ├─ tsconfig.json
|
|
|
|
|
|
│ ├─ vite.config.ts
|
|
|
|
|
|
│ └─ .env.example
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ docker/
|
|
|
|
|
|
│ ├─ Dockerfile.backend
|
|
|
|
|
|
│ ├─ Dockerfile.frontend
|
|
|
|
|
|
│ ├─ docker-compose.dev.yml
|
|
|
|
|
|
│ ├─ docker-compose.prod.yml
|
|
|
|
|
|
│ └─ nginx.conf
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ docs/
|
|
|
|
|
|
│ ├─ API.md ← API документация
|
|
|
|
|
|
│ ├─ DEPLOYMENT.md ← Деплой
|
|
|
|
|
|
│ └─ ARCHITECTURE.md ← Этот файл
|
|
|
|
|
|
│
|
|
|
|
|
|
├─ .gitignore
|
|
|
|
|
|
├─ README.md
|
|
|
|
|
|
└─ docker-compose.yml ← Главный compose
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔄 Поток данных (детально):
|
|
|
|
|
|
|
|
|
|
|
|
### **1. Загрузка паспорта с OCR:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
[React] Пользователь загружает passport.jpg
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] PassportUpload.tsx
|
|
|
|
|
|
↓ FormData
|
|
|
|
|
|
[FastAPI] POST /api/v1/documents/scan
|
|
|
|
|
|
↓
|
|
|
|
|
|
[FastAPI] DocumentService
|
|
|
|
|
|
├─► S3Service.upload() → s3_url
|
|
|
|
|
|
├─► RabbitMQ.publish('ocr_queue', {s3_url, type: 'passport'})
|
|
|
|
|
|
└─► return {"job_id": "abc-123", "status": "processing"}
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] Показывает: "⏳ Распознаём паспорт..."
|
|
|
|
|
|
[React] WebSocket подключение: ws://api/ws/jobs/abc-123
|
|
|
|
|
|
↓
|
|
|
|
|
|
[Worker] OCR Worker получает из RabbitMQ
|
|
|
|
|
|
├─► OCRService.analyze(s3_url) → текст (3 сек)
|
|
|
|
|
|
├─► AIService.extract_passport(text) → JSON (2 сек)
|
|
|
|
|
|
├─► PostgreSQL.log(processing_result)
|
|
|
|
|
|
└─► WebSocket.send_to_client(session_id, result)
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] WebSocket получает результат
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] Автозаполняет поля:
|
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
|
lastname: "Иванов",
|
|
|
|
|
|
firstname: "Иван",
|
|
|
|
|
|
...
|
|
|
|
|
|
})
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] Показывает: "✅ Паспорт распознан! Проверьте данные."
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Время**: ~5 секунд, но пользователь видит прогресс!
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### **2. Проверка рейса:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
[React] Пользователь ввёл "SU1234" и дату
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] FlightChecker.tsx
|
|
|
|
|
|
↓ debounce 500ms (не дёргаем API на каждый символ)
|
|
|
|
|
|
[FastAPI] GET /api/v1/flights/check?number=SU1234&date=2025-10-24
|
|
|
|
|
|
↓
|
|
|
|
|
|
[FastAPI] FlightService
|
|
|
|
|
|
├─► Redis.get('flight:SU1234:2025-10-24')
|
|
|
|
|
|
│ └─► Если есть → возврат из кеша (0.001 сек)
|
|
|
|
|
|
│
|
|
|
|
|
|
└─► Если нет:
|
|
|
|
|
|
├─► FlightAwareAPI.check() (1-2 сек)
|
|
|
|
|
|
├─► Redis.set('flight:...', result, ttl=3600) ← Кеш на час
|
|
|
|
|
|
└─► return result
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] Показывает красивую карточку:
|
|
|
|
|
|
┌─────────────────────────────────────┐
|
|
|
|
|
|
│ ✈️ Рейс SU1234 │
|
|
|
|
|
|
│ Moscow (SVO) → Ufa (UFA) │
|
|
|
|
|
|
│ Статус: ⚠️ Задержка 45 минут │
|
|
|
|
|
|
│ Вылет: 09:25 (план: 08:40) │
|
|
|
|
|
|
└─────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### **3. Отправка обращения:**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
[React] Пользователь заполнил всё, жмёт "Подать обращение"
|
|
|
|
|
|
↓
|
|
|
|
|
|
[FastAPI] POST /api/v1/claims/submit
|
|
|
|
|
|
{
|
|
|
|
|
|
client: {lastname, firstname, ...},
|
|
|
|
|
|
flight: {number, date, type: "delay_flight"},
|
|
|
|
|
|
documents: [s3_urls],
|
|
|
|
|
|
sbp_phone: "+79991234567"
|
|
|
|
|
|
}
|
|
|
|
|
|
↓
|
|
|
|
|
|
[FastAPI] ClaimService
|
|
|
|
|
|
├─► Валидация (Pydantic)
|
|
|
|
|
|
├─► PostgreSQL: сохранение claim (для аналитики)
|
|
|
|
|
|
├─► Формирование payload для CRM
|
|
|
|
|
|
│ {
|
|
|
|
|
|
│ "client": {...},
|
|
|
|
|
|
│ "contractor": {...}, ← Из конфига
|
|
|
|
|
|
│ "project": {...},
|
|
|
|
|
|
│ "ticket": {...}
|
|
|
|
|
|
│ }
|
|
|
|
|
|
├─► POST → https://form.clientright.ru/server_webservice2.php
|
|
|
|
|
|
│ └─► PHP Bridge → Vtiger Webservices (PHP 7.3)
|
|
|
|
|
|
│ └─► CRM создаёт тикет
|
|
|
|
|
|
│
|
|
|
|
|
|
├─► RabbitMQ.publish('notifications', {...}) ← Email в фоне
|
|
|
|
|
|
└─► return {"success": true, "ticket_id": "TT12345"}
|
|
|
|
|
|
↓
|
|
|
|
|
|
[React] Редирект на Success.tsx
|
|
|
|
|
|
"✅ Ваше обращение #TT12345 принято!"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🔌 Интеграции (детально):
|
|
|
|
|
|
|
|
|
|
|
|
### **OCR + Vision Pipeline:**
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
# services/document_processor.py
|
|
|
|
|
|
|
|
|
|
|
|
async def process_passport(file_url: str) -> PassportData:
|
|
|
|
|
|
# 1. OCR (ваш сервис)
|
|
|
|
|
|
ocr_response = await ocr_service.analyze(
|
|
|
|
|
|
file_url=file_url,
|
|
|
|
|
|
file_type="auto" # Автоопределение
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
ocr_text = ocr_response['pages_data'][0]['ocr_text']
|
|
|
|
|
|
|
|
|
|
|
|
# 2. Vision AI (OpenRouter Gemini)
|
|
|
|
|
|
vision_prompt = """
|
|
|
|
|
|
Извлеки из текста паспорта РФ следующие данные в формате JSON:
|
|
|
|
|
|
{
|
|
|
|
|
|
"surname": "...",
|
|
|
|
|
|
"name": "...",
|
|
|
|
|
|
"patronymic": "...",
|
|
|
|
|
|
"birthdate": "DD.MM.YYYY",
|
|
|
|
|
|
"passport_series": "XXXX",
|
|
|
|
|
|
"passport_number": "XXXXXX"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Текст паспорта:
|
|
|
|
|
|
{ocr_text}
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
vision_result = await ai_service.extract_structured_data(
|
|
|
|
|
|
prompt=vision_prompt.format(ocr_text=ocr_text)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 3. Валидация через Pydantic
|
|
|
|
|
|
passport = PassportData(**vision_result)
|
|
|
|
|
|
|
|
|
|
|
|
# 4. Логирование в PostgreSQL
|
|
|
|
|
|
await db.execute("""
|
|
|
|
|
|
INSERT INTO document_processing
|
|
|
|
|
|
(file_url, document_type, ocr_text, vision_result, processing_time_ms)
|
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
|
|
|
|
""", file_url, 'passport', ocr_text, vision_result, elapsed_ms)
|
|
|
|
|
|
|
|
|
|
|
|
return passport
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📡 API Спецификация:
|
|
|
|
|
|
|
|
|
|
|
|
### **Базовый URL:**
|
|
|
|
|
|
```
|
|
|
|
|
|
DEV: http://localhost:8000/api/v1
|
|
|
|
|
|
PROD: https://api.erv-claims.clientright.ru/api/v1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### **Endpoints:**
|
|
|
|
|
|
|
|
|
|
|
|
| Method | Endpoint | Описание | Время |
|
|
|
|
|
|
|--------|----------|----------|-------|
|
|
|
|
|
|
| POST | `/documents/upload` | Загрузка в S3 | ~500ms |
|
|
|
|
|
|
| POST | `/documents/scan` | OCR + Vision | ~5s (async) |
|
|
|
|
|
|
| GET | `/flights/check` | Проверка рейса | ~200ms (cache) |
|
|
|
|
|
|
| GET | `/policies/verify` | Проверка полиса | ~5ms (cache) |
|
|
|
|
|
|
| POST | `/claims/submit` | Создание обращения | ~1s |
|
|
|
|
|
|
| WS | `/ws/jobs/{job_id}` | Real-time статусы | - |
|
|
|
|
|
|
|
|
|
|
|
|
### **Пример: Scan Passport**
|
|
|
|
|
|
|
|
|
|
|
|
**Request:**
|
|
|
|
|
|
```http
|
|
|
|
|
|
POST /api/v1/documents/scan
|
|
|
|
|
|
Content-Type: application/json
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
"file_url": "https://s3.twcstorage.ru/.../passport.jpg",
|
|
|
|
|
|
"document_type": "passport"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**Response (сразу):**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
|
"status": "processing",
|
|
|
|
|
|
"estimated_time_seconds": 5
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**WebSocket update (через 5 сек):**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
|
|
|
|
"status": "completed",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"surname": "Иванов",
|
|
|
|
|
|
"name": "Иван",
|
|
|
|
|
|
"patronymic": "Иванович",
|
|
|
|
|
|
"birthdate": "01.01.1990",
|
|
|
|
|
|
"passport_series": "4510",
|
|
|
|
|
|
"passport_number": "123456"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🗄️ Структура баз данных:
|
|
|
|
|
|
|
|
|
|
|
|
### **PostgreSQL (новые данные):**
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- Обращения (дубликат для аналитики)
|
|
|
|
|
|
CREATE TABLE claims (
|
|
|
|
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
|
|
session_id VARCHAR(100),
|
|
|
|
|
|
insurance_type VARCHAR(50), -- erv_flight, erv_train, etc.
|
|
|
|
|
|
|
|
|
|
|
|
-- Данные клиента (JSONB)
|
|
|
|
|
|
client_data JSONB,
|
|
|
|
|
|
|
|
|
|
|
|
-- Данные события (JSONB)
|
|
|
|
|
|
event_data JSONB,
|
|
|
|
|
|
|
|
|
|
|
|
-- Документы
|
|
|
|
|
|
documents JSONB, -- [{type, s3_url, ocr_result, vision_result}]
|
|
|
|
|
|
|
|
|
|
|
|
-- Статус
|
|
|
|
|
|
status VARCHAR(20), -- processing, submitted, completed, error
|
|
|
|
|
|
crm_ticket_id VARCHAR(50),
|
|
|
|
|
|
|
|
|
|
|
|
-- Метаданные
|
|
|
|
|
|
ip_address INET,
|
|
|
|
|
|
user_agent TEXT,
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW(),
|
|
|
|
|
|
updated_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX idx_claims_status ON claims(status);
|
|
|
|
|
|
CREATE INDEX idx_claims_created ON claims(created_at);
|
|
|
|
|
|
CREATE INDEX idx_claims_crm_ticket ON claims(crm_ticket_id);
|
|
|
|
|
|
|
|
|
|
|
|
-- Обработка документов
|
|
|
|
|
|
CREATE TABLE document_processing (
|
|
|
|
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
|
|
|
|
claim_id UUID REFERENCES claims(id),
|
|
|
|
|
|
|
|
|
|
|
|
file_url TEXT,
|
|
|
|
|
|
s3_url TEXT,
|
|
|
|
|
|
document_type VARCHAR(50), -- passport, ticket, etc.
|
|
|
|
|
|
|
|
|
|
|
|
-- OCR результат
|
|
|
|
|
|
ocr_text TEXT,
|
|
|
|
|
|
ocr_confidence NUMERIC,
|
|
|
|
|
|
|
|
|
|
|
|
-- Vision результат
|
|
|
|
|
|
vision_result JSONB,
|
|
|
|
|
|
|
|
|
|
|
|
-- Метрики
|
|
|
|
|
|
processing_time_ms INTEGER,
|
|
|
|
|
|
ocr_time_ms INTEGER,
|
|
|
|
|
|
vision_time_ms INTEGER,
|
|
|
|
|
|
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
-- Логи
|
|
|
|
|
|
CREATE TABLE logs (
|
|
|
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
|
|
level VARCHAR(10), -- INFO, WARNING, ERROR
|
|
|
|
|
|
logger VARCHAR(50), -- ocr_service, flight_service, etc.
|
|
|
|
|
|
message TEXT,
|
|
|
|
|
|
context JSONB,
|
|
|
|
|
|
|
|
|
|
|
|
session_id VARCHAR(100),
|
|
|
|
|
|
ip_address INET,
|
|
|
|
|
|
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
CREATE INDEX idx_logs_level ON logs(level);
|
|
|
|
|
|
CREATE INDEX idx_logs_created ON logs(created_at DESC);
|
|
|
|
|
|
CREATE INDEX idx_logs_session ON logs(session_id);
|
|
|
|
|
|
|
|
|
|
|
|
-- Кеш API (fallback)
|
|
|
|
|
|
CREATE TABLE api_cache (
|
|
|
|
|
|
cache_key VARCHAR(255) PRIMARY KEY,
|
|
|
|
|
|
cache_value JSONB,
|
|
|
|
|
|
expires_at TIMESTAMP,
|
|
|
|
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
|
|
|
|
);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### **MySQL (существующая CRM база):**
|
|
|
|
|
|
|
|
|
|
|
|
```sql
|
|
|
|
|
|
-- НЕ трогаем! Только читаем
|
|
|
|
|
|
ci20465_erv.lexrpiority
|
|
|
|
|
|
├─ voucher
|
|
|
|
|
|
├─ insured_from
|
|
|
|
|
|
└─ insured_to
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🚀 Deployment стратегия:
|
|
|
|
|
|
|
|
|
|
|
|
### **Development (сейчас):**
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 1. Backend
|
|
|
|
|
|
cd backend
|
|
|
|
|
|
python -m venv venv
|
|
|
|
|
|
source venv/bin/activate
|
|
|
|
|
|
pip install -r requirements.txt
|
|
|
|
|
|
uvicorn app.main:app --reload --port 8000
|
|
|
|
|
|
|
|
|
|
|
|
# 2. Frontend
|
|
|
|
|
|
cd frontend
|
|
|
|
|
|
npm install
|
|
|
|
|
|
npm run dev # Vite dev server на :5173
|
|
|
|
|
|
|
|
|
|
|
|
# 3. Доступ:
|
|
|
|
|
|
Frontend: http://localhost:5173
|
|
|
|
|
|
Backend: http://localhost:8000
|
|
|
|
|
|
API Docs: http://localhost:8000/docs ← Swagger UI!
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### **Production (потом):**
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# Вариант 1: Тот же сервер, другой домен
|
|
|
|
|
|
cd /var/www/erv-claims.clientright.ru/
|
|
|
|
|
|
git clone http://147.45.146.17:3002/fedya/erv-platform.git .
|
|
|
|
|
|
docker-compose -f docker/docker-compose.prod.yml up -d
|
|
|
|
|
|
|
|
|
|
|
|
# Nginx конфиг:
|
|
|
|
|
|
server {
|
|
|
|
|
|
server_name erv-claims.clientright.ru;
|
|
|
|
|
|
|
|
|
|
|
|
# Frontend (статика)
|
|
|
|
|
|
location / {
|
|
|
|
|
|
root /var/www/erv-claims/frontend/dist;
|
|
|
|
|
|
try_files $uri $uri/ /index.html;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Backend API
|
|
|
|
|
|
location /api/ {
|
|
|
|
|
|
proxy_pass http://localhost:8000;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# WebSocket
|
|
|
|
|
|
location /ws/ {
|
|
|
|
|
|
proxy_pass http://localhost:8000;
|
|
|
|
|
|
proxy_http_version 1.1;
|
|
|
|
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
|
|
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 Что делаю СЕЙЧАС (следующие 2-3 часа):
|
|
|
|
|
|
|
|
|
|
|
|
### **Создаю базу:**
|
|
|
|
|
|
|
|
|
|
|
|
1. ✅ Структура проекта (сделано)
|
|
|
|
|
|
2. ✅ requirements.txt (Python зависимости)
|
|
|
|
|
|
3. ✅ package.json (React зависимости)
|
|
|
|
|
|
4. ✅ .env.example
|
|
|
|
|
|
5. ✅ Базовый FastAPI app
|
|
|
|
|
|
6. ✅ Базовый React app
|
|
|
|
|
|
7. ✅ SQL миграции для PostgreSQL
|
|
|
|
|
|
8. ✅ Docker compose для dev
|
|
|
|
|
|
9. ✅ README с инструкциями
|
|
|
|
|
|
|
|
|
|
|
|
**Время**: ~1 час на базовую настройку
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 💪 Готов?
|
|
|
|
|
|
|
|
|
|
|
|
Сейчас создам всю базовую структуру и запущу оба приложения (FastAPI + React).
|
|
|
|
|
|
|
|
|
|
|
|
**Начинаю прямо сейчас!** 🚀
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|