// ======================================== // Code Node: Мерж данных проекта в сессию // v2.0 - с расширенным логированием для отладки // ======================================== // 1. Берём первый item const inputItem = $input.all()[0]; if (!inputItem || !inputItem.json) { throw new Error('Пустой input в Code Node (нет json)'); } // root — то, что реально пришло в эту ноду const root = inputItem.json; // ✅ ОТЛАДКА: смотрим что пришло console.log('🔍 DEBUG: root keys:', Object.keys(root)); console.log('🔍 DEBUG: root.body exists:', !!root.body); console.log('🔍 DEBUG: root.other exists:', !!root.other); // 2. Универсально получаем body // - если нода стоит сразу после Webhook → данные лежат в root.body // - если кто-то выше уже отдал только body → root и есть body const body = root.body || root; console.log('🔍 DEBUG: body keys:', Object.keys(body)); console.log('🔍 DEBUG: body.other exists:', !!body.other); console.log('🔍 DEBUG: body.other type:', typeof body.other); // 3. Парсим body.other (если есть) как сессию // ✅ ВАЖНО: Также проверяем root.other напрямую (если данные пришли не через body) let sessionData = {}; let rawOther = body.other || root.other; // ✅ Пробуем также достать other из Webhook напрямую if (!rawOther) { try { const webhookJson = $('Webhook').first()?.json; if (webhookJson?.body?.other) { rawOther = webhookJson.body.other; console.log('✅ Взяли other напрямую из Webhook'); } } catch (e) { console.log('⚠️ Не удалось достать other из Webhook:', e.message); } } console.log('🔍 DEBUG: rawOther exists:', !!rawOther); console.log('🔍 DEBUG: rawOther type:', typeof rawOther); if (rawOther) { console.log('🔍 DEBUG: rawOther preview:', typeof rawOther === 'string' ? rawOther.substring(0, 200) : JSON.stringify(rawOther).substring(0, 200)); } if (rawOther) { if (typeof rawOther === 'string') { try { sessionData = JSON.parse(rawOther); console.log('✅ Распарсили other как JSON. Ключи:', Object.keys(sessionData)); console.log('✅ sessionData.session_id:', sessionData.session_id); console.log('✅ sessionData.phone:', sessionData.phone); console.log('✅ sessionData.firstname:', sessionData.firstname); } catch (e) { throw new Error('Не смог распарсить other как JSON: ' + e.message + '. rawOther: ' + rawOther.substring(0, 500)); } } else if (typeof rawOther === 'object') { sessionData = rawOther; console.log('✅ other уже объект. Ключи:', Object.keys(sessionData)); } } else { console.log('⚠️ other отсутствует или пустой. Проверьте структуру данных!'); console.log('⚠️ root:', JSON.stringify(root).substring(0, 500)); } // 4. Определяем claimId (основной путь) let claimId = body.claim_id || sessionData.claim_id || null; // 5. Fallback: пробуем достать claim_id напрямую из Webhook, если его до сих пор нет if (!claimId) { try { const webhookNodeJson = $('Webhook').first()?.json; if (webhookNodeJson?.body?.claim_id) { claimId = webhookNodeJson.body.claim_id; } } catch (e) { // молча игнорируем, просто не удалось взять из Webhook } } // 6. Если всё ещё нет claimId — это реально критичная ситуация if (!claimId) { throw new Error( 'Нет claim_id ни в body, ни в sessionData, ни в Webhook. ' + 'body: ' + JSON.stringify(body) + ', sessionData: ' + JSON.stringify(sessionData) ); } // 7. Забираем результат ноды CreateClientProject (или CreateWebPorject, если опечатка в названии ноды) let projectNode = null; let projectNodeName = null; // Пробуем найти ноду безопасно try { projectNode = $node["CreateClientProject"]; if (projectNode && projectNode.json) { projectNodeName = "CreateClientProject"; } } catch (e) { // Нода CreateClientProject не найдена, пробуем альтернативное название } if (!projectNode || !projectNode.json) { try { projectNode = $node["CreateWebPorject"]; if (projectNode && projectNode.json) { projectNodeName = "CreateWebPorject"; } } catch (e) { // Нода CreateWebPorject тоже не найдена } } if (!projectNode || !projectNode.json) { throw new Error('Нет данных от ноды CreateClientProject/CreateWebPorject. Убедитесь, что нода существует и выполнена.'); } const projectResult = projectNode.json.result; // Ожидаем что-то типа: { "project_id": "398095", "project_name": "Иванов_КлиентПрав", "is_new": false } if (!projectResult || !projectResult.project_id) { throw new Error('Нет projectResult.project_id. result: ' + JSON.stringify(projectNode.json)); } // 8. Собираем обновлённую сессию // ✅ Используем spread оператор, но с фильтрацией undefined значений // Сначала создаём базовый объект из sessionData, фильтруя undefined const baseSession = Object.keys(sessionData).reduce((acc, key) => { if (sessionData[key] !== undefined && sessionData[key] !== null) { acc[key] = sessionData[key]; } return acc; }, {}); console.log('📦 baseSession после фильтрации:', Object.keys(baseSession)); console.log('📦 baseSession sample:', { session_id: baseSession.session_id, phone: baseSession.phone, unified_id: baseSession.unified_id, contact_id: baseSession.contact_id, firstname: baseSession.firstname, lastname: baseSession.lastname, }); const updatedSession = { // ✅ Шаг 1: Все данные из sessionData (body.other) - базовая сессия ...baseSession, // ✅ Шаг 2: Дополняем данными из body (если их нет в sessionData) ...(body.phone && !baseSession.phone ? { phone: body.phone } : {}), ...(body.unified_id && !baseSession.unified_id ? { unified_id: body.unified_id } : {}), ...(body.contact_id && !baseSession.contact_id ? { contact_id: body.contact_id } : {}), ...(body.email && !baseSession.email ? { email: body.email } : {}), // ✅ Шаг 3: Данные проекта (новые, всегда перезаписываем) claim_id: claimId, // актуальный claim_id (перезаписываем null из sessionData) project_id: projectResult.project_id, // id проекта из CRM project_name: projectResult.project_name || null, // название проекта из CRM is_new_project: projectResult.is_new, // флаг новый/старый current_step: 2, // двигаем визард на шаг 2 // ✅ Шаг 4: Данные анализа из body (приоритет body) problem: body.problem || baseSession.problem || null, last_analysis_output: body.output || baseSession.last_analysis_output || null, // ✅ Шаг 5: Метаданные (всегда обновляем) updated_at: new Date().toISOString(), }; // ✅ Логируем результат для отладки console.log('📦 sessionData keys:', Object.keys(sessionData)); console.log('📦 sessionData sample:', { session_id: sessionData.session_id, phone: sessionData.phone, unified_id: sessionData.unified_id, contact_id: sessionData.contact_id, firstname: sessionData.firstname, lastname: sessionData.lastname, middle_name: sessionData.middle_name, }); console.log('📦 updatedSession keys:', Object.keys(updatedSession)); console.log('📦 updatedSession sample:', { session_id: updatedSession.session_id, phone: updatedSession.phone, unified_id: updatedSession.unified_id, contact_id: updatedSession.contact_id, firstname: updatedSession.firstname, lastname: updatedSession.lastname, middle_name: updatedSession.middle_name, claim_id: updatedSession.claim_id, project_id: updatedSession.project_id, }); console.log('📦 updatedSession FULL:', JSON.stringify(updatedSession, null, 2)); // 9. Возвращаем один item для Redis SET return [ { json: { redis_key: `claim:${claimId}`, redis_value: JSON.stringify(updatedSession), ttl: 604800, // 7 дней }, }, ];