Files
aiform_prod/docs/SESSION_LOG_2025-11-20.md
AI Assistant 0978e485dc feat: Add claim plan confirmation flow via Redis SSE
Problem:
- After wizard form submission, need to wait for claim data from n8n
- Claim data comes via Redis channel claim:plan:{session_token}
- Need to display confirmation form with claim data

Solution:
1. Backend: Added SSE endpoint /api/v1/claim-plan/{session_token}
   - Subscribes to Redis channel claim:plan:{session_token}
   - Streams claim data from n8n to frontend
   - Handles timeouts and errors gracefully

2. Frontend: Added subscription to claim:plan channel
   - StepWizardPlan: After form submission, subscribes to SSE
   - Waits for claim_plan_ready event
   - Shows loading message while waiting
   - On success: saves claimPlanData and shows confirmation step

3. New component: StepClaimConfirmation
   - Displays claim confirmation form in iframe
   - Receives claimPlanData from parent
   - Generates HTML form (placeholder - should call n8n for real HTML)
   - Handles confirmation/cancellation via postMessage

4. ClaimForm: Added conditional step for confirmation
   - Shows StepClaimConfirmation when showClaimConfirmation=true
   - Step appears after StepWizardPlan
   - Only visible when claimPlanData is available

Flow:
1. User fills wizard form → submits
2. Form data sent to n8n via /api/v1/claims/wizard
3. Frontend subscribes to SSE /api/v1/claim-plan/{session_token}
4. n8n processes data → publishes to Redis claim:plan:{session_token}
5. Backend receives → streams to frontend via SSE
6. Frontend receives → shows StepClaimConfirmation
7. User confirms → proceeds to next step

Files:
- backend/app/api/events.py: Added stream_claim_plan endpoint
- frontend/src/components/form/StepWizardPlan.tsx: Added subscribeToClaimPlan
- frontend/src/components/form/StepClaimConfirmation.tsx: New component
- frontend/src/pages/ClaimForm.tsx: Added confirmation step to steps array
2025-11-24 13:36:14 +03:00

117 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лог сессии разработки - 20 ноября 2025
## Проблема (из предыдущей сессии)
После верификации телефона не отображался список черновиков, хотя в базе данных есть заявки с `unified_id`.
## Решение
### 1. Исправлен SQL запрос в backend (`claims.py`)
**Проблема:** Запрос строился через конкатенацию строк, что могло приводить к проблемам с параметрами.
**Решение:** Переписан SQL запрос - теперь используется прямой запрос для каждого случая:
- Для `unified_id`: прямой запрос `WHERE c.unified_id = $1`
- Для `phone`: подзапрос через `clpr_user_accounts` и `clpr_users`
- Для `session_id`: прямой запрос `WHERE c.session_token = $1`
```python
if unified_id:
query = """
SELECT
c.id,
c.payload->>'claim_id' as claim_id,
c.session_token,
c.status_code,
c.channel,
c.payload,
c.created_at,
c.updated_at
FROM clpr_claims c
WHERE c.unified_id = $1
ORDER BY c.updated_at DESC
LIMIT 20
"""
params = [unified_id]
```
### 2. Улучшена обработка черновиков в frontend (`ClaimForm.tsx`)
**Проблема:** Черновики из Telegram имеют другую структуру данных (данные в `payload.body`), а не напрямую в `payload`.
**Решение:** Добавлена поддержка обоих форматов:
- **Telegram формат:** данные в `payload.body.wizard_plan`, `payload.body.answers`
- **Web form формат:** данные напрямую в `payload.wizard_plan`, `payload.answers`
```typescript
// ✅ Для telegram черновиков данные могут быть в payload.body
const body = payload.body || {};
const isTelegramFormat = !!payload.body;
// ✅ Извлекаем данные из body (telegram) или напрямую из payload (web_form)
const wizardPlanRaw = body.wizard_plan || payload.wizard_plan;
const answersRaw = body.answers || payload.answers;
const problemDescription = body.problem_description || payload.problem_description || body.description || payload.description;
// ✅ Парсим wizard_plan и answers, если они строки (JSON)
let wizardPlan = wizardPlanRaw;
if (typeof wizardPlanRaw === 'string') {
try {
wizardPlan = JSON.parse(wizardPlanRaw);
} catch (e) {
console.warn('⚠️ Не удалось распарсить wizard_plan:', e);
}
}
```
### 3. Улучшена обработка `claim_id`
**Проблема:** `claim_id` может быть в разных местах в зависимости от формата данных.
**Решение:** Добавлен поиск `claim_id` в нескольких местах:
```typescript
const finalClaimId = claim.claim_id || payload.claim_id || body.claim_id || claim.id || formData.claim_id || claimId;
```
### 4. Добавлено детальное логирование
- В `loadDraft`: логирование всех этапов загрузки черновика
- В `get_draft` (backend): логирование найденных данных
- В `list_drafts` (backend): тестовые COUNT запросы для отладки
### 5. Исправлена обработка `claim_id` в backend
В `get_draft` теперь извлекается `claim_id` из `payload`, если его нет в `row`:
```python
claim_id_from_payload = payload.get('claim_id') if isinstance(payload, dict) else None
final_claim_id = row.get('claim_id') or claim_id_from_payload
```
## Результат
**Черновики теперь возвращаются!** API корректно возвращает список черновиков для `unified_id`.
## Файлы изменены
1. `backend/app/api/claims.py`:
- Переписан SQL запрос для `list_drafts`
- Добавлено логирование и тестовые COUNT запросы
- Улучшена обработка `claim_id` в `get_draft`
2. `frontend/src/pages/ClaimForm.tsx`:
- Добавлена поддержка формата Telegram черновиков
- Улучшена обработка `claim_id` из разных источников
- Добавлено детальное логирование загрузки черновика
3. `frontend/src/components/form/Step1Phone.tsx`:
- (Возможно, были изменения для передачи unified_id)
4. `frontend/src/components/form/StepDraftSelection.tsx`:
- (Возможно, были изменения для отображения черновиков)
## Текущий статус
**Работает:** API возвращает черновики
**Работает:** Загрузка черновиков поддерживает оба формата (Telegram и web_form)
⚠️ **Требует проверки:** Отображение черновиков в UI (StepDraftSelection)
## Следующие шаги
1. Проверить отображение черновиков в UI
2. Протестировать загрузку черновика из Telegram формата
3. Убедиться, что все данные корректно восстанавливаются в форму