Files
aiform_dev/docs/N8N_CLAIMSAVE_PRIMARY_SETUP.md
AI Assistant 3621ae6021 feat: Session persistence with Redis + Draft management fixes
- Implement session management API (/api/v1/session/create, verify, logout)
- Add session restoration from localStorage on page reload
- Fix session_id priority when loading drafts (use current, not old from DB)
- Add unified_id and claim_id to wizard payload sent to n8n
- Add Docker volume for frontend HMR (Hot Module Replacement)
- Add comprehensive session logging for debugging

Components updated:
- backend/app/api/session.py (NEW) - Session management endpoints
- backend/app/main.py - Include session router
- frontend/src/components/form/Step1Phone.tsx v2.0 - Create session after SMS
- frontend/src/pages/ClaimForm.tsx v3.8 - Session restoration & priority fix
- frontend/src/components/form/StepWizardPlan.tsx v1.4 - Add unified_id/claim_id
- docker-compose.yml - Add frontend volume for live reload

Session flow:
1. User verifies phone -> session created in Redis (24h TTL)
2. session_token saved to localStorage
3. Page reload -> session restored automatically
4. Draft selected -> current session_id used (not old from DB)
5. Wizard submit -> unified_id, claim_id, session_id sent to n8n
6. Logout -> session removed from Redis & localStorage

Fixes:
- Session token not persisting after page reload
- unified_id missing in n8n webhook payload
- Old session_id from draft overwriting current session
- Frontend changes requiring container rebuild
2025-11-20 18:31:42 +03:00

226 lines
9.5 KiB
Markdown
Raw 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.

# Инструкция: Добавление узла `claimsave_primary` в workflow b4K4u851b4JFivyD
## Позиция узла
**Между узлами:**
- **После:** `Code4` (форматирует данные для Redis)
- **Перед:** `push_wizard1` (пушит wizard_plan в Redis для SSE)
## Порядок узлов в workflow
```
1. Redis Trigger
2. get_claime_data1
3. Edit Fields8
4. Merge2
5. Get row(s) in sheet2
6. Edit Fields16
7. AI Agent1
8. пробрасываем факт фул и факт шорт1
9. AI Agent13
10. output_set1
11. Edit Fields11
12. AI Agent12
13. Code
14. Code4
15. ⭐ Code: Prepare Claimsave Data ← ВСТАВИТЬ ЗДЕСЬ (Code Node)
16. ⭐ claimsave_primary ← ВСТАВИТЬ ЗДЕСЬ (PostgreSQL)
17. push_wizard1
```
## Шаги настройки
### 1. Добавить Code Node для подготовки данных
**Рекомендуется:** Добавить Code Node перед PostgreSQL для удобства отладки и валидации данных.
1. Откройте workflow `b4K4u851b4JFivyD` в n8n
2. Найдите узел `Code4`
3. Добавьте новый узел **Code** после `Code4`
4. Назовите узел: `Code: Prepare Claimsave Data`
5. Подключите:
- **Вход:** от узла `Code4`
- **Выход:** к узлу `claimsave_primary` (PostgreSQL)
**Код для Code Node:** См. файл `docs/CODE_CLAIMSAVE_PRIMARY_PREPARE.js`
**Режим выполнения:** `Run Once for All Items`
### 2. Добавить новый узел PostgreSQL
1. Откройте workflow `b4K4u851b4JFivyD` в n8n
2. Найдите узел `Code4`
3. Добавьте новый узел **PostgreSQL** после `Code4`
4. Назовите узел: `claimsave_primary`
5. Подключите:
- **Вход:** от узла `Code4`
- **Выход:** к узлу `push_wizard1`
### 2. Настройка PostgreSQL узла
**Connection:** Выберите подключение к PostgreSQL (то же, что используется в других узлах)
**Operation:** `Execute Query`
**Query:** Вставьте SQL из файла `docs/SQL_CLAIMSAVE_PRIMARY_DRAFT_CLEAN.sql` (чистая версия без плейсхолдеров)
**⚠️ ВАЖНО:** Используйте файл `SQL_CLAIMSAVE_PRIMARY_DRAFT_CLEAN.sql`, а не `SQL_CLAIMSAVE_PRIMARY_DRAFT.sql`!
### 3. Параметры запроса
**Query Replacement:** Оставьте пустым (не используем)
**Parameters:** Добавьте 3 параметра (если используете Code Node для подготовки):
#### Параметр $1 (payload_json):
```javascript
{{ JSON.stringify($('Code: Prepare Claimsave Data').first().json.payload_json) }}
```
#### Параметр $2 (session_token):
```javascript
{{ $('Code: Prepare Claimsave Data').first().json.session_token }}
```
#### Параметр $3 (unified_id):
```javascript
{{ $('Code: Prepare Claimsave Data').first().json.unified_id }}
```
**Примечание:** Code Node берёт `unified_id` из ноды `propertyName` (приоритет: `propertyName` > `Edit Fields10` > `Redis Trigger`)
---
**Альтернатива (без Code Node):** Если не используете Code Node, можно собрать данные напрямую:
#### Параметр $1 (payload_json):
```javascript
{{ JSON.stringify({
problem_description: $('Edit Fields16').first().json.chatInput,
wizard_plan: $('Code4').first().json.redis_value.wizard_plan,
answers_prefill: $('Code4').first().json.redis_value.answers_prefill || [],
coverage_report: $('Code4').first().json.redis_value.coverage_report || {},
ai_agent1_facts: {
facts_short: $('пробрасываем факт фул и факт шорт1').first().json.facts_short,
facts_full: $('пробрасываем факт фул и факт шорт1').first().json.facts_full,
problem: $('пробрасываем факт фул и факт шорт1').first().json.problem
},
ai_agent13_rag: $('AI Agent13').first().json.output,
phone: $('Redis Trigger').first().json.message.phone,
email: $('Redis Trigger').first().json.message.email || null,
type_code: $('Code4').first().json.redis_value.wizard_plan?.case_type || 'consumer'
}) }}
```
#### Параметр $2 (session_token):
```javascript
{{ $('Edit Fields11').first().json.session_token || $('Redis Trigger').first().json.message.session_id }}
```
#### Параметр $3 (unified_id):
```javascript
{{ $('propertyName').first().json.unified_id || $('Edit Fields10').first().json.unified_id || $('Redis Trigger').first().json.message.unified_id || null }}
```
**Примечание:** Приоритет источников `unified_id`: `propertyName` > `Edit Fields10` > `Redis Trigger`
### 4. Проверка подключений
Убедитесь, что:
- ✅ Узел `Code: Prepare Claimsave Data` получает данные от `Code4`
- ✅ Узел `claimsave_primary` получает данные от `Code: Prepare Claimsave Data`
- ✅ Узел `push_wizard1` получает данные от `claimsave_primary` (или от `Code4`, если нужно)
-Все пути данных корректны
## Преимущества использования Code Node
**Упрощение параметров PostgreSQL:** Вместо сложных выражений в параметрах SQL, используем простые ссылки на Code Node
**Валидация данных:** Code Node проверяет наличие обязательных полей и выводит предупреждения
**Отладка:** Легче отслеживать, какие данные собраны, через логи Code Node
**Обработка edge cases:** Можно добавить fallback значения и обработку ошибок
**Читаемость:** Код подготовки данных отделён от SQL запроса
## Что сохраняется
После выполнения узла `claimsave_primary` в БД будет создана/обновлена запись в `clpr_claims`:
-`session_token` - для связи
-`unified_id` - если передан
-`status_code = 'draft'` - статус черновика
-`payload.wizard_plan` - план вопросов
-`payload.problem_description` - описание проблемы
-`payload.answers_prefill` - предзаполненные ответы
-`payload.coverage_report` - отчёт о покрытии
-`payload.ai_agent1_facts` - факты из AI Agent1
-`payload.ai_agent13_rag` - RAG ответ
-`payload.phone`, `payload.email` - контакты
- ⚠️ `payload.claim_id = NULL` - будет сгенерирован позже
## Возвращаемое значение
Узел возвращает объект:
```json
{
"claim": {
"claim_id": "uuid-записи",
"session_token": "sess-...",
"status_code": "draft",
"payload": { ... }
}
}
```
## Важные замечания
1. **Узел работает в режиме UPSERT:**
- Если запись с таким `session_token` существует → обновляет её
- Если записи нет → создаёт новую
2. **`claim_id` генерируется позже:**
- На этом этапе `claim_id` в `payload` = `NULL`
- UUID записи (`clpr_claims.id`) используется как временный идентификатор
- Позже `claim_id` будет сгенерирован в формате `CLM-YYYY-MM-DD-XXXXXX`
3. **Данные из предыдущих узлов:**
- `wizard_plan` берётся из `Code4.redis_value.wizard_plan`
- `problem_description` берётся из `Edit Fields16.chatInput`
- `ai_agent1_facts` берётся из узла `пробрасываем факт фул и факт шорт1`
- `ai_agent13_rag` берётся из `AI Agent13.output`
## Тестирование
После добавления узла:
1. Запустите workflow с тестовыми данными
2. Проверьте, что узел выполняется без ошибок
3. Проверьте в БД, что запись создана/обновлена:
```sql
SELECT id, session_token, unified_id, status_code, payload->>'wizard_plan'
FROM clpr_claims
WHERE session_token = 'sess-...'
ORDER BY updated_at DESC
LIMIT 1;
```
## Если что-то не работает
1. **Ошибка "column does not exist":**
- Проверьте, что все поля в SQL запросе существуют в таблице `clpr_claims`
2. **Ошибка "invalid input syntax for type jsonb":**
- Проверьте, что параметр `$1` правильно сериализован через `JSON.stringify()`
- Убедитесь, что все вложенные объекты корректны
3. **Ошибка "session_token is null":**
- Проверьте, что `Edit Fields11` содержит `session_token`
- Проверьте fallback на `Redis Trigger.message.session_id`
4. **Данные не сохраняются:**
- Проверьте логи n8n на наличие ошибок
- Проверьте, что все узлы-источники данных выполнены успешно