- Перенос телефона на первый шаг с SMS верификацией
- Создана операция CreateWebContact в vTiger CRM
- N8N workflow: контакт + claim_id + Redis session
- Docker-compose: убраны локальные postgres/redis
- Backend подключён к внешним сервисам
- Флаг is_new_contact для UX (новый vs существующий клиент)
- Исправлено 7 проблем (Postgres v16, Redis, N8N webhooks, Gitea)
- Готовность к черновикам и личному кабинету
- docker-compose.yml: убраны локальные postgres/redis, только внешние
- Frontend: телефон в формате 79001234567 (без +)
- Готово к интеграции с n8n webhook для создания контакта в CRM
- CreateWebContact: только создание или возврат ID, БЕЗ обновления
Детальный лог работы по спрятыванию webhook URLs:
- Backend proxy для n8n
- Webhook URLs в .env
- Исправления проблем (относительные пути, event_type, пропущенные поля)
- Полная документация SECURITY_N8N_PROXY.md
- 4 коммита, все проблемы решены
Результат: Webhook URLs больше не видны в коде фронтенда
Проблема: Frontend ждал event_type='ocr_completed', но n8n отправлял 'policy_ocr_completed'
Из-за этого событие не обрабатывалось и показывалась ошибка
Решение: Гибкая проверка event_type:
- ocr_completed (старый формат)
- policy_ocr_completed (новый формат из n8n)
- любой *_ocr_completed (includes)
Теперь работает с любыми workflow которые шлют разные типы событий
Проблема: Backend proxy не передавал filename и upload_timestamp к n8n
Это ломало обработку файлов в workflow
Изменения:
- Добавлены параметры filename и upload_timestamp в proxy_file_upload()
- Теперь передаём все поля которые отправляет frontend
Было в n8n body: {claim_id, voucher, session_id, file_type}
Стало: {claim_id, voucher, session_id, file_type, filename, upload_timestamp}
Проблема: Frontend в Docker не мог достучаться до http://localhost:8100
Решение: Используем '/api/n8n/*' - Vite proxy автоматически перенаправит на backend
Изменения:
- Step1Policy.tsx: fetch('/api/n8n/policy/check')
- Step1Policy.tsx: fetch('/api/n8n/upload/file')
- StepDocumentUpload.tsx: fetch('/api/n8n/upload/file')
Vite proxy настроен в vite.config.ts:
/api -> host.docker.internal:8100
/events -> host.docker.internal:8100
- Создан n8n_proxy.py для безопасного проксирования запросов
- Webhook URLs перенесены в .env (скрыты от фронтенда)
- Frontend теперь использует /api/n8n/* endpoints
- Добавлена документация SECURITY_N8N_PROXY.md
Преимущества:
- Webhook URLs не видны в DevTools
- Централизованное логирование
- Возможность добавить rate limiting и auth
- Легко менять URLs без пересборки фронтенда
- Документирован полный рефакторинг визарда (Вариант B)
- Каждый документ = отдельный шаг в прогресс-баре
- Созданы Step2EventType.tsx, StepDocumentUpload.tsx, documentConfigs.ts
- Переделан ClaimForm.tsx на динамические шаги через useMemo
- Исправлены проблемы: URL n8n, FormData структура, SSE логирование
- Исправлены прогресс и навигация через useCallback
- Всего 9 коммитов, ~1500 строк кода
- Обернул nextStep, prevStep, updateFormData, handleSubmit в useCallback
- Теперь функции стабильны и не пересоздаются при ререндере
- nextStep и prevStep используют functional update для setState
- Добавлено логирование навигации: '⏩ nextStep' и '⏪ prevStep'
- Исправлены зависимости useMemo для steps
ПРОБЛЕМА: prevStep вызывался, но setCurrentStep не обновлял стейт
РЕШЕНИЕ: useCallback гарантирует что функции стабильны
- Добавлен disabled={false} для основной кнопки Назад
- Добавлен disabled={false} для DEV кнопок (Назад и Пропустить)
- Добавлено логирование при нажатии для отладки
- Теперь кнопки гарантированно кликабельны
- Изменён console.error на console.log для нормального закрытия SSE
- Теперь показывается '✅ SSE закрыто после получения результата - всё ОК'
- Реальная ошибка выводится только если данные не получены
- Консоль больше не пугает красными ошибками при успешной работе
- Upload: добавлен disabled во время загрузки
- Upload onChange: правильная обработка newFileList
- Кнопка Назад: убран disabled - теперь всегда доступна
- DEV кнопка Назад: также убран disabled
- Добавлено логирование handleUpload и onChange для отладки
- Создан Step2EventType.tsx для выбора типа страхового случая
- Создан StepDocumentUpload.tsx - универсальный компонент для загрузки одного документа
- Создан constants/documentConfigs.ts с конфигурацией документов для всех типов событий
- Переделан ClaimForm.tsx на динамическое создание шагов через useMemo
- Прогресс-бар теперь показывает: [Полис] → [Тип] → [Док1] → [Док2] → [Оплата]
- Бэкап старого Step2Details сохранён как Step2Details.OLD_WIZARD_INLINE.tsx
- Каждый документ загружается на отдельном шаге с модалкой обработки
- SSE для каждого документа с уникальным event_type
- DEV MODE кнопки для быстрой навигации на всех шагах
Проблема: После строки 657 весь код компонента дублировался,
что вызывало синтаксическую ошибку 'Unexpected token' на строке 659.
Решение: Удалены строки 659-820 (дубликат кода).
🎯 Изменения:
- Документы загружаются по очереди (один за другим)
- После загрузки каждого документа открывается модалка с крутилкой
- SSE слушает конкретный event_type: {file_type}_processed
- Модалка показывает результат распознавания с извлечёнными данными
- Кнопка 'Продолжить' → переход к следующему документу
- Опциональные документы можно пропустить
- После обработки всех обязательных → 'Далее на Step 3'
📊 UX флоу:
1. Выбор типа события → показываются нужные документы
2. Документ 1: Выбрать файл → Загрузить → Модалка → Результат → Продолжить
3. Документ 2: Выбрать файл → Загрузить → Модалка → Результат → Продолжить
4. Документ 3 (опц): Загрузить ИЛИ Пропустить
5. Все обязательные обработаны → Далее на Step 3
🔑 Каждый документ получает свой уникальный event_type:
- frontend отправляет file_type
- n8n возвращает event_type = {file_type}_processed
- frontend слушает этот конкретный event_type через SSE
🤖 Переход на OCR/AI для извлечения данных из документов:
✅ Изменения:
- Убран ручной ввод полей (дата, номер рейса и тд)
- Добавлена умная загрузка документов в зависимости от типа события
- Каждый тип документа получает уникальный file_type для n8n
- Валидация обязательных документов перед переходом
📋 Типы документов и их file_type:
1. Задержка рейса:
- flight_delay_boarding_or_ticket (обяз)
- flight_delay_confirmation (обяз)
2. Отмена рейса:
- flight_cancel_ticket (обяз)
- flight_cancel_notice (обяз)
3. Пропуск стыковки:
- connection_arrival_boarding (обяз)
- connection_departure_boarding_or_ticket (обяз)
- connection_delay_proof (опц)
4. Поезд (задержка):
- train_ticket (обяз)
- train_delay_proof (обяз)
5. Поезд (отмена):
- train_ticket (обяз)
- train_cancel_proof (обяз)
6. Паром:
- ferry_ticket (обяз)
- ferry_delay_proof (обяз)
7. Запасной аэродром:
- emergency_boarding_or_ticket (обяз)
- emergency_landing_proof (обяз)
🔑 file_type позволяет n8n разделять потоки и применять разные AI промпты
для каждого типа документа.
Backup старой версии: Step2Details.OLD_MANUAL_INPUT.tsx
Создана копия Step2Details.OLD_MANUAL_INPUT.tsx перед переходом на
умную форму с автоматическим распознаванием документов через OCR/AI.
В случае необходимости можно вернуться к ручному вводу.
✅ При успешном распознавании полиса - кнопка 'Продолжить →' → переход на Step 2
❌ При ошибке распознавания - кнопка 'Загрузить другой файл' → возврат к форме загрузки
Проблема: Backend закрывает SSE после отправки события, браузер триггерит onerror,
фронтенд перезаписывал успешный результат сообщением 'Ошибка подключения к серверу'.
Решение: Проверяем в onerror что если уже получили результат (prev !== 'loading'),
не затираем его ошибкой.
🎯 Основные изменения:
Backend:
- Реализован SSE endpoint /events/{task_id} для real-time стриминга событий
- Интеграция Redis Pub/Sub для получения событий от n8n
- Исправлен путь к .env файлу (абсолютный путь)
- Убран префикс /api/v1 для events router
- Добавлено подробное логирование событий
Frontend:
- Переключён на Vite dev mode для работы proxy
- Настроен proxy /events -> backend:8100
- Реализована модалка с крутилкой при загрузке файла
- SSE клиент для получения OCR результатов в real-time
- Отображение результатов AI анализа в модалке
Docker:
- Frontend: изменён на npm run dev (Vite dev server)
- Добавлен host.docker.internal для доступа к backend
- Настроен proxy в docker-compose
Утилиты:
- monitor_redis_direct.py - мониторинг Redis Pub/Sub
- test_redis_publish_direct.py - тестирование публикации в Redis
🚀 Полная цепочка работает:
Frontend → Backend SSE → Redis Pub/Sub ← n8n → OCR/AI → Result
Включает:
- 🎯 Описание архитектуры React → n8n → Redis → SSE
- 🔧 Все реализованные компоненты (Backend, Frontend, n8n workflows)
- 🐛 Решённые проблемы и их фиксы
- 📊 Метрики производительности
- 📝 Credentials и важные URL
- ✅ Достигнутые результаты
- 🔮 Следующие шаги
КРИТИЧЕСКОЕ ИСПРАВЛЕНИЕ:
✅ OCR endpoint: /process → /analyze-file
✅ Исправлено в 3 местах:
- ocr_service.py (line 48)
- upload.py x2 (policy + passport endpoints)
Проблема:
- POST http://147.45.146.17:8001/process → 404 Not Found
- OCR не работал
- Gemini Vision не получал данные
Дополнительные исправления:
✅ Условные поля для стыковочного рейса (4 поля)
✅ Поле для подтверждения отмены рейса
✅ OCR polling с progress bar
✅ Убран некорректный статус 'Полис найден'
SESSION_LOG:
- Добавлена полная история 25 октября
- 12 коммитов задокументированы
- Статистика: ~2000 строк, 25 файлов, 15 проблем решено
- Список известных проблем (DOCX не поддерживается)
Следующие шаги:
1. Перезапустить backend (обязательно!)
2. Протестировать OCR на PDF/JPG файлах
3. Проверить Gemini Vision анализ в Debug панели
1. ✅ OCR Progress Bar:
- Добавлен polling OCR результатов каждые 3 сек
- Визуальный индикатор: 🔍 Обработка OCR... (1/10)
- Progress bar с анимацией
- Статусы: 🔄 Запуск → 🔍 Обработка → ✅ Завершен
- Gemini Vision результаты в Debug панели
2. ✅ Убран некорректный 'Полис найден':
- Было: показывался сразу после загрузки файла
- Проблема: OCR еще не закончился, может быть шляпа
- Решение: убрана зеленая плашка с Step2
- Статус полиса только после реальной проверки
3. ✅ Условные поля для стыковочного рейса:
- Если выбран 'miss_connection' → показываются 4 доп поля:
• Номер рейса прибытия
• Дата рейса прибытия
• Номер рейса отправления
• Дата рейса отправления
- Если выбран 'cancel_flight' → доп поле:
• Подтверждение отмены от АК
- Для обычных рейсов: только номер рейса
Frontend изменения:
- Step1Policy: OCR polling, progress bar
- Step2Details: условная логика полей (как в erv_ticket)
- useState для eventType
- handleEventTypeChange для динамики
Теперь:
✅ Видно прогресс OCR
✅ Видно результаты Gemini Vision
✅ Условные поля работают
✅ Нет ложных статусов
Проблема:
❌ Queue error: 'str' object has no attribute 'get'
❌ ocr_result не инициализировался до try блока
❌ Debug панель не показывала OCR результаты
Решение:
✅ Добавлена инициализация: ocr_result = None
✅ Убрана проверка 'ocr_result' in locals()
✅ Теперь ocr_result всегда определен
Что изменилось:
- Backend не падает при OCR ошибках
- OCR результаты возвращаются в response
- Debug панель получает ocr_result
- Логи показывают процесс OCR
Тестирование:
Загрузи файл полиса → Debug панель покажет:
📤 Upload to S3
🔍 OCR running
📄 OCR completed: XXX chars
🤖 AI analysis: policy/garbage
✅ Extracted data
Проблема: На Step3 кнопка Назад была только ПОСЛЕ верификации телефона
Решение: Вынес кнопку Назад в начало формы (до блока телефона)
Теперь:
✅ Кнопка '← Назад' видна ВСЕГДА на Step3
✅ Можно вернуться на Step2 в любой момент
✅ Не нужно ждать верификацию телефона
UX улучшение: пользователь не застревает на Step3
Step2Details (по скриншоту):
✅ Индикатор '✅ Полис найден' вверху
✅ Select с типами событий из erv_ticket:
- Задержка авиарейса (более 3 часов)
- Отмена авиарейса
- Пропуск стыковочного рейса
- Посадка на запасной аэродром
- Задержка отправки поезда
- Отмена поезда
- Задержка/отмена парома/круизного судна
✅ Дата наступления страхового случая (DatePicker)
✅ Номер рейса/поезда/парома
✅ Загрузка подтверждающих документов:
- Посадочный талон, билет, справка и т.д.
- До 10 файлов по 15MB
- HEIC, PDF, фото
Debug Panel улучшения:
✅ Полные S3 URL (не обрезанные)
✅ Кнопка '🔗 Открыть в новой вкладке'
✅ word-break: break-all для длинных URL
✅ Показывает все файлы из массива
✅ Для каждого файла:
- Filename
- File ID (UUID)
- Size (KB)
- Полный S3 URL (кликабельный)
Теперь в Debug видно КУДА загрузилось:
https://s3.twcstorage.ru/f9825c87-.../policies/20251024_213045_abc123_file.jpg
Можно кликнуть и посмотреть глазами! 👀
Новый UI:
✅ Split-screen layout:
- Слева (60%): форма заявки
- Справа (40%): Debug Console в реальном времени
Компонент DebugPanel.tsx:
✅ Темная тема (VS Code style)
✅ Timeline с событиями
✅ Real-time обновления
✅ Показывает:
- Form Data (JSON в реальном времени)
- Events Log с иконками и цветами
- Детали каждого события
События которые отображаются:
1. policy_check:
- ✅ Полис найден в MySQL БД
- ⚠️ Полис не найден
- Показывает: voucher, found status
2. upload:
- 📤 Загружаю X файлов в S3
- ✅ Загружено в S3: X/Y
- Показывает: file_id, size, S3 URL
3. ocr:
- 🔍 Запущен OCR
- 📄 OCR завершен: XXX символов
- Показывает: текст preview
4. ai_analysis:
- 🤖 AI: policy/garbage, confidence: 95%
- 🗑️ ШЛЯПА DETECTED! (пользователю не говорим)
- Показывает: document_type, is_valid, confidence, extracted_data
5. sms:
- 📱 Отправляю SMS
- ✅ SMS отправлен (DEBUG mode)
- 🔐 Проверяю код
- ✅ Телефон подтвержден
- Показывает: phone, debug_code
UX:
- Sticky panel (прилипает при скролле)
- Monospace шрифт для данных
- Цветовая кодировка статусов
- JSON форматирование
Layout:
- Row + Col от Ant Design
- Responsive: mobile = 1 column, desktop = split
Теперь видно ВСЁ что происходит в реальном времени! 🔍