Files
aiform_dev/docs/CODE_CLAIMSAVE_PRIMARY_PREPARE.js
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

164 lines
6.9 KiB
JavaScript
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.

// ============================================================================
// Code Node: Подготовка данных для claimsave_primary
// ============================================================================
// Назначение: Собрать все данные из предыдущих узлов и подготовить payload
// для сохранения первичного черновика в PostgreSQL
//
// Позиция: После Code4, перед claimsave_primary (PostgreSQL)
// ============================================================================
const items = $input.all();
// Получаем данные из разных узлов
const code4Data = $('Code4').first().json.redis_value || {};
const editFields16 = $('Edit Fields16').first().json;
const aiAgent1Facts = $('пробрасываем факт фул и факт шорт1').first().json;
const aiAgent13 = $('AI Agent13').first().json;
const redisTrigger = $('Redis Trigger').first().json.message || {};
const editFields11 = $('Edit Fields11').first().json || {};
const editFields10 = $('Edit Fields10').first().json || {};
const propertyNameRaw = $('propertyName').first().json || {};
// propertyName может быть массивом или объектом
// Если массив - берем первый элемент, если объект - используем как есть
const propertyName = Array.isArray(propertyNameRaw)
? (propertyNameRaw[0] || {})
: propertyNameRaw;
// Логирование для отладки unified_id
console.log('🔍 Поиск unified_id:');
console.log(' - propertyNameRaw (тип):', Array.isArray(propertyNameRaw) ? 'массив' : 'объект');
console.log(' - propertyName:', propertyName);
console.log(' - propertyName.unified_id:', propertyName?.unified_id);
console.log(' - propertyName.body?.unified_id:', propertyName?.body?.unified_id);
console.log(' - propertyName.result?.unified_id:', propertyName?.result?.unified_id);
console.log(' - editFields10.unified_id:', editFields10?.unified_id);
console.log(' - redisTrigger.unified_id:', redisTrigger?.unified_id);
// Собираем payload для сохранения
const payload = {
// Описание проблемы от пользователя
problem_description: editFields16?.chatInput || redisTrigger?.description || null,
// Wizard plan от AI Agent12 (через Code4)
wizard_plan: code4Data.wizard_plan || null,
// Предзаполненные ответы (если есть)
answers_prefill: code4Data.answers_prefill || [],
// Отчёт о покрытии (если есть)
coverage_report: code4Data.coverage_report || {},
// Данные из AI Agent1 (факты)
ai_agent1_facts: {
facts_short: aiAgent1Facts?.facts_short || null,
facts_full: aiAgent1Facts?.facts_full || null,
problem: aiAgent1Facts?.problem || null
},
// Данные из AI Agent13 (RAG ответ)
ai_agent13_rag: aiAgent13?.output || null,
// Контакты
phone: redisTrigger?.phone || null,
email: redisTrigger?.email || null,
// Тип дела (из wizard_plan или по умолчанию)
type_code: code4Data.wizard_plan?.case_type || 'consumer'
};
// Получаем session_token (приоритет: Edit Fields11 > Redis Trigger)
const session_token = editFields11.session_token
|| redisTrigger.session_id
|| null;
// Получаем unified_id (приоритет: propertyName > Edit Fields10 > Redis Trigger)
// propertyName может быть массивом, объектом, или содержать unified_id в вложенных объектах
let unified_id = null;
// Если propertyName - массив, ищем unified_id в элементах массива
if (Array.isArray(propertyNameRaw)) {
for (const item of propertyNameRaw) {
unified_id = item?.unified_id
|| item?.body?.unified_id
|| item?.result?.unified_id
|| item?.data?.unified_id
|| null;
if (unified_id) break;
}
} else {
// Если propertyName - объект, ищем unified_id напрямую или в вложенных объектах
unified_id = propertyName.unified_id
|| propertyName.body?.unified_id
|| propertyName.result?.unified_id
|| propertyName.data?.unified_id
|| null;
}
// Fallback на другие источники
if (!unified_id) {
unified_id = editFields10.unified_id
|| redisTrigger.unified_id
|| null;
}
// Валидация обязательных полей
if (!session_token) {
throw new Error('❌ session_token не найден! Проверьте узлы Edit Fields11 и Redis Trigger.');
}
if (!payload.wizard_plan) {
console.warn('⚠️ wizard_plan отсутствует! Черновик будет сохранён без плана вопросов.');
}
if (!payload.problem_description) {
console.warn('⚠️ problem_description отсутствует! Черновик будет сохранён без описания проблемы.');
}
// Логирование для отладки
console.log('🔍 Подготовка данных для claimsave_primary:');
console.log(' - session_token:', session_token ? '✅' : '❌');
console.log(' - unified_id:', unified_id || 'null');
if (!unified_id) {
console.warn('⚠️ unified_id не найден! Проверьте ноды: propertyName, Edit Fields10, Redis Trigger');
}
console.log(' - wizard_plan:', payload.wizard_plan ? '✅' : '❌');
console.log(' - problem_description:', payload.problem_description ? '✅' : '❌');
console.log(' - ai_agent1_facts:', payload.ai_agent1_facts.facts_short ? '✅' : '❌');
console.log(' - ai_agent13_rag:', payload.ai_agent13_rag ? '✅' : '❌');
console.log(' - phone:', payload.phone || 'null');
console.log(' - email:', payload.email || 'null');
// Возвращаем данные для PostgreSQL узла
return {
json: {
// Payload для параметра $1
payload_json: payload,
// Session token для параметра $2
session_token: session_token,
// Unified ID для параметра $3 (может быть null)
unified_id: unified_id,
// Дополнительная информация для отладки
_debug: {
has_wizard_plan: !!payload.wizard_plan,
has_problem_description: !!payload.problem_description,
has_ai_agent1: !!payload.ai_agent1_facts.facts_short,
has_ai_agent13: !!payload.ai_agent13_rag,
source_nodes: {
code4: 'Code4',
editFields16: 'Edit Fields16',
aiAgent1: 'пробрасываем факт фул и факт шорт1',
aiAgent13: 'AI Agent13',
redisTrigger: 'Redis Trigger',
editFields11: 'Edit Fields11',
editFields10: 'Edit Fields10',
propertyName: 'propertyName'
}
}
}
};