Files
aiform_prod/docs/NEW_FLOW_ARCHITECTURE.md
AI Assistant 02689e65db fix: Исправление загрузки документов и SQL запросов
- Исправлена потеря документов при обновлении черновика (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
2025-11-26 19:54:51 +03:00

24 KiB
Raw Blame History

🚀 Новая архитектура: Быстрая загрузка документов

Дата создания: 2025-11-26
Статус: В разработке


📋 Проблема

Текущий флоу слишком медленный:

  1. 2 минуты — генерация визарда (RAG + AI анализ)
  2. Длинная анкета — слишком много вопросов для пользователя

Новое решение

Концепция

  1. После описания проблемы → сразу запрашиваем документы (без ожидания визарда)
  2. Пока пользователь загружает документы → в бэке генерируется визард + OCR
  3. После всех документов → показываем готовое заявление на апрув

Преимущества

  • Быстрый старт — пользователь не ждёт 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 — публикация описания в Redis
  • GET /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)

  1. Создать StepDocumentsNew.tsx — заглушка с mock данными
  2. Создать StepWaitingClaim.tsx — loader
  3. Обновить ClaimForm.tsx — новый флоу шагов
  4. Обновить StepDraftSelection.tsx — новые статусы

Фаза 2: Backend

  1. Эндпоинт POST /api/v1/documents/upload
  2. SSE events: documents_list_ready, document_ocr_completed, claim_ready
  3. Эндпоинт GET /api/v1/claims/drafts/{claim_id}/status

Фаза 3: n8n

  1. Воркфлоу: Генерация списка документов
  2. Воркфлоу: OCR документа
  3. Воркфлоу: Формирование заявления

Фаза 4: Интеграция и тестирование

  1. Полный цикл с реальными данными
  2. Обработка ошибок
  3. Legacy черновики

🎯 Ожидаемый результат

Метрика Было Стало
Время до первого действия ~2 мин ~10 сек
Количество вопросов 10-15 0-3 (только уточняющие)
Конверсия ? ↑ (меньше отвала)

Дата создания: 2025-11-26
Статус: В разработке


📋 Проблема

Текущий флоу слишком медленный:

  1. 2 минуты — генерация визарда (RAG + AI анализ)
  2. Длинная анкета — слишком много вопросов для пользователя

Новое решение

Концепция

  1. После описания проблемы → сразу запрашиваем документы (без ожидания визарда)
  2. Пока пользователь загружает документы → в бэке генерируется визард + OCR
  3. После всех документов → показываем готовое заявление на апрув

Преимущества

  • Быстрый старт — пользователь не ждёт 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 — публикация описания в Redis
  • GET /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)

  1. Создать StepDocumentsNew.tsx — заглушка с mock данными
  2. Создать StepWaitingClaim.tsx — loader
  3. Обновить ClaimForm.tsx — новый флоу шагов
  4. Обновить StepDraftSelection.tsx — новые статусы

Фаза 2: Backend

  1. Эндпоинт POST /api/v1/documents/upload
  2. SSE events: documents_list_ready, document_ocr_completed, claim_ready
  3. Эндпоинт GET /api/v1/claims/drafts/{claim_id}/status

Фаза 3: n8n

  1. Воркфлоу: Генерация списка документов
  2. Воркфлоу: OCR документа
  3. Воркфлоу: Формирование заявления

Фаза 4: Интеграция и тестирование

  1. Полный цикл с реальными данными
  2. Обработка ошибок
  3. Legacy черновики

🎯 Ожидаемый результат

Метрика Было Стало
Время до первого действия ~2 мин ~10 сек
Количество вопросов 10-15 0-3 (только уточняющие)
Конверсия ? ↑ (меньше отвала)