- Исправлена потеря документов при обновлении черновика (SQL объединяет вместо перезаписи) - Исправлено определение типа документа (приоритет field_label над field_name) - Исправлены дубликаты в documents_meta и documents_uploaded - Добавлена передача group_index с фронтенда для правильного field_name - Исправлены все документы в таблице clpr_claim_documents с правильными field_name - Обновлены SQL запросы: claimsave и claimsave_final для нового флоу - Добавлена поддержка multi-file upload для одного документа - Исправлены дубликаты в списке загруженных документов на фронтенде Файлы: - SQL: SQL_CLAIMSAVE_FIXED_NEW_FLOW.sql, SQL_CLAIMSAVE_FINAL_FIXED_NEW_FLOW_WITH_UPLOADED.sql - n8n: N8N_CODE_PROCESS_UPLOADED_FILES_FIXED.js (поддержка group_index) - Backend: documents.py (передача group_index в n8n) - Frontend: StepWizardPlan.tsx (передача group_index, исправление дубликатов) - Скрипты: fix_claim_documents_field_names.py, fix_documents_meta_duplicates.py Результат: документы больше не теряются, имеют правильные типы и field_name
24 KiB
24 KiB
🚀 Новая архитектура: Быстрая загрузка документов
Дата создания: 2025-11-26
Статус: В разработке
📋 Проблема
Текущий флоу слишком медленный:
- 2 минуты — генерация визарда (RAG + AI анализ)
- Длинная анкета — слишком много вопросов для пользователя
✅ Новое решение
Концепция
- После описания проблемы → сразу запрашиваем документы (без ожидания визарда)
- Пока пользователь загружает документы → в бэке генерируется визард + OCR
- После всех документов → показываем готовое заявление на апрув
Преимущества
- Быстрый старт — пользователь не ждёт 2 минуты
- Параллельная работа — OCR и визард генерируются пока пользователь ищет документы
- Меньше вопросов — большая часть данных извлекается из документов
🔄 Новый флоу (шаги)
┌─────────────────┐
│ 1. Телефон │ (уже есть)
│ SMS верификация
└────────┬────────┘
▼
┌─────────────────┐
│ 2. Черновики │ (уже есть, обновить UI)
│ - Новые статусы│
│ - Legacy→"Начать заново"
└────────┬────────┘
▼
┌─────────────────┐
│ 3. Описание │ (уже есть)
│ Свободный текст│
└────────┬────────┘
│
▼ → n8n: быстрая генерация списка документов (5-10 сек)
│ → n8n: параллельно запускает генерацию визарда (в фоне)
▼
┌─────────────────┐
│ 4. Документы │ 🆕 НОВЫЙ КОМПОНЕНТ
│ - Поэкранная загрузка
│ - Критичные помечены
│ - Можно пропустить
└────────┬────────┘
│
▼ → n8n: OCR каждого документа → заполнение визарда (в фоне)
│
▼
┌─────────────────┐
│ 5. Ожидание │ 🆕 НОВЫЙ КОМПОНЕНТ
│ "Формируем заявление..."
│ Loader + прогресс
└────────┬────────┘
│
▼ ← n8n: claim_ready event (SSE)
▼
┌─────────────────┐
│ 6. Заявление │ (уже есть StepClaimConfirmation)
│ Просмотр + редактирование
└────────┬────────┘
▼
┌─────────────────┐
│ 7. SMS апрув │ (уже есть)
└─────────────────┘
📊 Статусы черновика (status_code)
| Статус | Описание | UI при открытии |
|---|---|---|
draft_new |
Только описание | → Шаг документов |
draft_docs_progress |
Часть документов загружена | → Продолжить с текущего документа |
draft_docs_complete |
Все документы загружены | → Показать loader |
draft_claim_ready |
Заявление готово | → Показать заявление |
awaiting_sms |
Ждёт SMS | → Форма SMS |
approved |
Отправлено | Не показываем |
Legacy черновики (старый формат)
- Нет
documents_required→ показываем с пометкой "устаревший" - Кнопка "Начать заново" → копирует description, создаёт новый черновик
📦 Структура payload черновика
{
// === Идентификаторы ===
"claim_id": "CLM-2025-11-26-X7Y8Z9",
"session_token": "sess_abc123...",
"unified_id": "user_456...",
"phone": "+79991234567",
"email": "user@example.com",
// === Описание проблемы ===
"problem_description": "Купил курсы за 50000р, компания не отвечает...",
// === Документы (новое!) ===
"documents_required": [
{
"type": "contract",
"name": "Договор или оферта",
"critical": true,
"hints": "Скриншот или PDF договора/оферты"
},
{
"type": "payment",
"name": "Подтверждение оплаты",
"critical": true,
"hints": "Чек, выписка из банка, скриншот платежа"
},
{
"type": "correspondence",
"name": "Переписка с продавцом",
"critical": false,
"hints": "Скриншоты переписки, email, чаты"
}
],
"documents_uploaded": [
{
"type": "contract",
"file_id": "s3://...",
"ocr_status": "completed",
"ocr_data": {...}
}
],
"documents_skipped": ["correspondence"],
"current_doc_index": 1,
// === Визард (генерируется в фоне) ===
"wizard_plan": {...}, // AI-generated questions
"wizard_answers": {...}, // Auto-filled from OCR
"wizard_ready": true, // Флаг готовности
// === Заявление ===
"claim_ready": false, // Флаг готовности заявления
"claim_data": { // Готовое заявление для апрува
"applicant": {...},
"case": {...},
"contract_or_service": {...},
"offenders": [...],
"claim": {...},
"attachments": [...]
},
// === Метаданные ===
"created_at": "2025-11-26T10:00:00Z",
"updated_at": "2025-11-26T10:05:00Z"
}
🔌 API Endpoints
Существующие (без изменений)
POST /api/v1/claims/description— публикация описания в RedisGET /api/v1/claims/drafts/list— список черновиковGET /api/v1/claims/drafts/{claim_id}— полные данные черновикаPOST /api/v1/claims/approve— финальный апрув (SMS)
Новые/Изменённые
1. SSE: Получение списка документов
GET /api/v1/events/{session_id}
Event: documents_list_ready
Data: {
"event_type": "documents_list_ready",
"documents_required": [...]
}
2. Загрузка документа
POST /api/v1/documents/upload
Content-Type: multipart/form-data
Body:
- claim_id: string
- document_type: string (contract, payment, etc.)
- file: binary
Response:
{
"success": true,
"file_id": "s3://...",
"ocr_status": "processing"
}
3. SSE: Статус OCR и формирования заявления
GET /api/v1/events/{session_id}
Event: document_ocr_completed
Data: {
"event_type": "document_ocr_completed",
"document_type": "contract",
"ocr_data": {...}
}
Event: claim_ready
Data: {
"event_type": "claim_ready",
"claim_data": {...}
}
4. Получение статуса черновика
GET /api/v1/claims/drafts/{claim_id}/status
Response:
{
"status_code": "draft_docs_progress",
"documents_total": 3,
"documents_uploaded": 1,
"documents_skipped": 0,
"wizard_ready": false,
"claim_ready": false
}
🖥️ Frontend компоненты
1. StepDocumentsNew.tsx (НОВЫЙ)
// Поэкранная загрузка документов
// Один документ на экран
// Критичные помечены алертом
// Кнопки: "Загрузить", "Пропустить", "Назад"
interface Props {
documents: DocumentConfig[];
currentIndex: number;
onUpload: (file: File) => void;
onSkip: () => void;
onNext: () => void;
onPrev: () => void;
}
2. StepWaitingClaim.tsx (НОВЫЙ)
// Loader пока формируется заявление
// Прогресс: "OCR документов...", "Анализ данных...", "Формирование заявления..."
// SSE подписка на claim_ready
interface Props {
sessionId: string;
onClaimReady: (claimData: any) => void;
}
3. StepDraftSelection.tsx (ОБНОВИТЬ)
// Новые статусы черновиков
// Разные действия для разных статусов
// Legacy черновики → "Начать заново"
4. ClaimForm.tsx (ОБНОВИТЬ)
// Новая логика шагов
// Убрать StepWizardPlan из основного флоу
// Добавить StepDocumentsNew и StepWaitingClaim
⚙️ n8n Воркфлоу
1. Генерация списка документов (быстрая)
Redis Trigger (ticket_form:description)
↓
AI: Быстрый анализ → список документов (5-10 сек)
↓
Redis Publish (ocr_events:{session_id})
+ event_type: documents_list_ready
↓
PostgreSQL: Сохранить documents_required в черновик
↓
Параллельно: Запустить генерацию визарда (отдельный воркфлоу)
2. Генерация визарда (фоновая)
(Запускается из воркфлоу 1)
↓
AI Agent: RAG + генерация вопросов (2 мин)
↓
PostgreSQL: Сохранить wizard_plan в черновик
+ wizard_ready = true
3. OCR документа
Webhook (upload документа)
↓
S3 Upload
↓
AI Vision: OCR + извлечение данных
↓
PostgreSQL: Сохранить в documents_uploaded
↓
Redis Publish: document_ocr_completed
↓
Если все документы загружены:
↓ (Запустить формирование заявления)
4. Формирование заявления
(После всех документов)
↓
Собрать данные из:
- wizard_plan
- documents_uploaded (OCR данные)
- CRM контакт
↓
AI: Сформировать заявление
↓
PostgreSQL: Сохранить claim_data
+ claim_ready = true
↓
Redis Publish: claim_ready
📝 План реализации
Фаза 1: Frontend (без n8n)
- ✅ Создать
StepDocumentsNew.tsx— заглушка с mock данными - ✅ Создать
StepWaitingClaim.tsx— loader - ✅ Обновить
ClaimForm.tsx— новый флоу шагов - ✅ Обновить
StepDraftSelection.tsx— новые статусы
Фаза 2: Backend
- ✅ Эндпоинт
POST /api/v1/documents/upload - ✅ SSE events:
documents_list_ready,document_ocr_completed,claim_ready - ✅ Эндпоинт
GET /api/v1/claims/drafts/{claim_id}/status
Фаза 3: n8n
- ✅ Воркфлоу: Генерация списка документов
- ✅ Воркфлоу: OCR документа
- ✅ Воркфлоу: Формирование заявления
Фаза 4: Интеграция и тестирование
- ✅ Полный цикл с реальными данными
- ✅ Обработка ошибок
- ✅ Legacy черновики
🎯 Ожидаемый результат
| Метрика | Было | Стало |
|---|---|---|
| Время до первого действия | ~2 мин | ~10 сек |
| Количество вопросов | 10-15 | 0-3 (только уточняющие) |
| Конверсия | ? | ↑ (меньше отвала) |
Дата создания: 2025-11-26
Статус: В разработке
📋 Проблема
Текущий флоу слишком медленный:
- 2 минуты — генерация визарда (RAG + AI анализ)
- Длинная анкета — слишком много вопросов для пользователя
✅ Новое решение
Концепция
- После описания проблемы → сразу запрашиваем документы (без ожидания визарда)
- Пока пользователь загружает документы → в бэке генерируется визард + OCR
- После всех документов → показываем готовое заявление на апрув
Преимущества
- Быстрый старт — пользователь не ждёт 2 минуты
- Параллельная работа — OCR и визард генерируются пока пользователь ищет документы
- Меньше вопросов — большая часть данных извлекается из документов
🔄 Новый флоу (шаги)
┌─────────────────┐
│ 1. Телефон │ (уже есть)
│ SMS верификация
└────────┬────────┘
▼
┌─────────────────┐
│ 2. Черновики │ (уже есть, обновить UI)
│ - Новые статусы│
│ - Legacy→"Начать заново"
└────────┬────────┘
▼
┌─────────────────┐
│ 3. Описание │ (уже есть)
│ Свободный текст│
└────────┬────────┘
│
▼ → n8n: быстрая генерация списка документов (5-10 сек)
│ → n8n: параллельно запускает генерацию визарда (в фоне)
▼
┌─────────────────┐
│ 4. Документы │ 🆕 НОВЫЙ КОМПОНЕНТ
│ - Поэкранная загрузка
│ - Критичные помечены
│ - Можно пропустить
└────────┬────────┘
│
▼ → n8n: OCR каждого документа → заполнение визарда (в фоне)
│
▼
┌─────────────────┐
│ 5. Ожидание │ 🆕 НОВЫЙ КОМПОНЕНТ
│ "Формируем заявление..."
│ Loader + прогресс
└────────┬────────┘
│
▼ ← n8n: claim_ready event (SSE)
▼
┌─────────────────┐
│ 6. Заявление │ (уже есть StepClaimConfirmation)
│ Просмотр + редактирование
└────────┬────────┘
▼
┌─────────────────┐
│ 7. SMS апрув │ (уже есть)
└─────────────────┘
📊 Статусы черновика (status_code)
| Статус | Описание | UI при открытии |
|---|---|---|
draft_new |
Только описание | → Шаг документов |
draft_docs_progress |
Часть документов загружена | → Продолжить с текущего документа |
draft_docs_complete |
Все документы загружены | → Показать loader |
draft_claim_ready |
Заявление готово | → Показать заявление |
awaiting_sms |
Ждёт SMS | → Форма SMS |
approved |
Отправлено | Не показываем |
Legacy черновики (старый формат)
- Нет
documents_required→ показываем с пометкой "устаревший" - Кнопка "Начать заново" → копирует description, создаёт новый черновик
📦 Структура payload черновика
{
// === Идентификаторы ===
"claim_id": "CLM-2025-11-26-X7Y8Z9",
"session_token": "sess_abc123...",
"unified_id": "user_456...",
"phone": "+79991234567",
"email": "user@example.com",
// === Описание проблемы ===
"problem_description": "Купил курсы за 50000р, компания не отвечает...",
// === Документы (новое!) ===
"documents_required": [
{
"type": "contract",
"name": "Договор или оферта",
"critical": true,
"hints": "Скриншот или PDF договора/оферты"
},
{
"type": "payment",
"name": "Подтверждение оплаты",
"critical": true,
"hints": "Чек, выписка из банка, скриншот платежа"
},
{
"type": "correspondence",
"name": "Переписка с продавцом",
"critical": false,
"hints": "Скриншоты переписки, email, чаты"
}
],
"documents_uploaded": [
{
"type": "contract",
"file_id": "s3://...",
"ocr_status": "completed",
"ocr_data": {...}
}
],
"documents_skipped": ["correspondence"],
"current_doc_index": 1,
// === Визард (генерируется в фоне) ===
"wizard_plan": {...}, // AI-generated questions
"wizard_answers": {...}, // Auto-filled from OCR
"wizard_ready": true, // Флаг готовности
// === Заявление ===
"claim_ready": false, // Флаг готовности заявления
"claim_data": { // Готовое заявление для апрува
"applicant": {...},
"case": {...},
"contract_or_service": {...},
"offenders": [...],
"claim": {...},
"attachments": [...]
},
// === Метаданные ===
"created_at": "2025-11-26T10:00:00Z",
"updated_at": "2025-11-26T10:05:00Z"
}
🔌 API Endpoints
Существующие (без изменений)
POST /api/v1/claims/description— публикация описания в RedisGET /api/v1/claims/drafts/list— список черновиковGET /api/v1/claims/drafts/{claim_id}— полные данные черновикаPOST /api/v1/claims/approve— финальный апрув (SMS)
Новые/Изменённые
1. SSE: Получение списка документов
GET /api/v1/events/{session_id}
Event: documents_list_ready
Data: {
"event_type": "documents_list_ready",
"documents_required": [...]
}
2. Загрузка документа
POST /api/v1/documents/upload
Content-Type: multipart/form-data
Body:
- claim_id: string
- document_type: string (contract, payment, etc.)
- file: binary
Response:
{
"success": true,
"file_id": "s3://...",
"ocr_status": "processing"
}
3. SSE: Статус OCR и формирования заявления
GET /api/v1/events/{session_id}
Event: document_ocr_completed
Data: {
"event_type": "document_ocr_completed",
"document_type": "contract",
"ocr_data": {...}
}
Event: claim_ready
Data: {
"event_type": "claim_ready",
"claim_data": {...}
}
4. Получение статуса черновика
GET /api/v1/claims/drafts/{claim_id}/status
Response:
{
"status_code": "draft_docs_progress",
"documents_total": 3,
"documents_uploaded": 1,
"documents_skipped": 0,
"wizard_ready": false,
"claim_ready": false
}
🖥️ Frontend компоненты
1. StepDocumentsNew.tsx (НОВЫЙ)
// Поэкранная загрузка документов
// Один документ на экран
// Критичные помечены алертом
// Кнопки: "Загрузить", "Пропустить", "Назад"
interface Props {
documents: DocumentConfig[];
currentIndex: number;
onUpload: (file: File) => void;
onSkip: () => void;
onNext: () => void;
onPrev: () => void;
}
2. StepWaitingClaim.tsx (НОВЫЙ)
// Loader пока формируется заявление
// Прогресс: "OCR документов...", "Анализ данных...", "Формирование заявления..."
// SSE подписка на claim_ready
interface Props {
sessionId: string;
onClaimReady: (claimData: any) => void;
}
3. StepDraftSelection.tsx (ОБНОВИТЬ)
// Новые статусы черновиков
// Разные действия для разных статусов
// Legacy черновики → "Начать заново"
4. ClaimForm.tsx (ОБНОВИТЬ)
// Новая логика шагов
// Убрать StepWizardPlan из основного флоу
// Добавить StepDocumentsNew и StepWaitingClaim
⚙️ n8n Воркфлоу
1. Генерация списка документов (быстрая)
Redis Trigger (ticket_form:description)
↓
AI: Быстрый анализ → список документов (5-10 сек)
↓
Redis Publish (ocr_events:{session_id})
+ event_type: documents_list_ready
↓
PostgreSQL: Сохранить documents_required в черновик
↓
Параллельно: Запустить генерацию визарда (отдельный воркфлоу)
2. Генерация визарда (фоновая)
(Запускается из воркфлоу 1)
↓
AI Agent: RAG + генерация вопросов (2 мин)
↓
PostgreSQL: Сохранить wizard_plan в черновик
+ wizard_ready = true
3. OCR документа
Webhook (upload документа)
↓
S3 Upload
↓
AI Vision: OCR + извлечение данных
↓
PostgreSQL: Сохранить в documents_uploaded
↓
Redis Publish: document_ocr_completed
↓
Если все документы загружены:
↓ (Запустить формирование заявления)
4. Формирование заявления
(После всех документов)
↓
Собрать данные из:
- wizard_plan
- documents_uploaded (OCR данные)
- CRM контакт
↓
AI: Сформировать заявление
↓
PostgreSQL: Сохранить claim_data
+ claim_ready = true
↓
Redis Publish: claim_ready
📝 План реализации
Фаза 1: Frontend (без n8n)
- ✅ Создать
StepDocumentsNew.tsx— заглушка с mock данными - ✅ Создать
StepWaitingClaim.tsx— loader - ✅ Обновить
ClaimForm.tsx— новый флоу шагов - ✅ Обновить
StepDraftSelection.tsx— новые статусы
Фаза 2: Backend
- ✅ Эндпоинт
POST /api/v1/documents/upload - ✅ SSE events:
documents_list_ready,document_ocr_completed,claim_ready - ✅ Эндпоинт
GET /api/v1/claims/drafts/{claim_id}/status
Фаза 3: n8n
- ✅ Воркфлоу: Генерация списка документов
- ✅ Воркфлоу: OCR документа
- ✅ Воркфлоу: Формирование заявления
Фаза 4: Интеграция и тестирование
- ✅ Полный цикл с реальными данными
- ✅ Обработка ошибок
- ✅ Legacy черновики
🎯 Ожидаемый результат
| Метрика | Было | Стало |
|---|---|---|
| Время до первого действия | ~2 мин | ~10 сек |
| Количество вопросов | 10-15 | 0-3 (только уточняющие) |
| Конверсия | ? | ↑ (меньше отвала) |