{ "updatedAt": "2026-06-04T00:42:33.818Z", "createdAt": "2026-05-23T12:05:00.156Z", "id": "t6lFUulNtDIR3tAm", "name": "Chat de WhatsApp de propuestas ejecutadas", "description": null, "active": true, "isArchived": false, "nodes": [ { "parameters": { "httpMethod": "POST", "path": "6e314249-3d5f-4052-b303-0188d1da9e30", "responseMode": "responseNode", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -5584, -912 ], "id": "cd3b1b5e-bc1d-4879-bb5e-e3caa86d38c0", "name": "Webhook", "webhookId": "6e314249-3d5f-4052-b303-0188d1da9e30" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const input = $json || {};\nconst body = input.body || input;\nconst data = body.data || body;\n\nconst key =\n data.key ||\n data.message?.key ||\n input.key ||\n {};\n\nconst message =\n data.message ||\n data.messages?.[0]?.message ||\n input.message ||\n {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nfunction getRemoteJid() {\n return clean(\n input.remote_jid ||\n input.remoteJid ||\n key.remoteJid ||\n data.remoteJid ||\n data.chatId ||\n data.from ||\n data.sender ||\n ''\n );\n}\n\nfunction getPhoneFromJid(jid) {\n return onlyDigits(clean(jid).split('@')[0]);\n}\n\nfunction getTextFromMessage(msg) {\n return clean(\n input.texto ||\n input.text ||\n msg.conversation ||\n msg.extendedTextMessage?.text ||\n msg.imageMessage?.caption ||\n msg.videoMessage?.caption ||\n msg.documentMessage?.caption ||\n data.messageText ||\n data.text ||\n data.body ||\n ''\n );\n}\n\nfunction detectMessageType(msg) {\n if (input.message_type) return clean(input.message_type).toLowerCase();\n if (msg.imageMessage) return 'image';\n if (msg.videoMessage) return 'video';\n if (msg.audioMessage) return 'audio';\n if (msg.documentMessage) return 'document';\n if (msg.conversation || msg.extendedTextMessage) return 'text';\n return clean(data.messageType || data.type || 'unknown').toLowerCase();\n}\n\nfunction detectAccion(texto, messageType) {\n const t = norm(texto);\n\n const flujoDestino = norm(\n input.flujo_destino ||\n input.workflow_selected ||\n input.opcion_flujo ||\n ''\n );\n\n if (\n t === '2' ||\n t === 'INICIAR' ||\n t === 'INICIAR REPORTE' ||\n t === 'PROPUESTAS EJECUTADAS' ||\n flujoDestino.includes('PROPUESTAS EJECUTADAS') ||\n input.iniciar_flujo === true\n ) {\n return 'INICIAR';\n }\n\n if (t === 'CANCELAR' || t === 'CANCELAR REPORTE') {\n return 'CANCELAR';\n }\n\n if (t === 'FOTOS LISTAS' || t === 'IMAGENES LISTAS' || t === 'IMÁGENES LISTAS') {\n return 'FOTOS_LISTAS';\n }\n\n if (t === 'SIN VIDEO' || t === 'NO TENGO VIDEO' || t === 'NO HAY VIDEO') {\n return 'SIN_VIDEO';\n }\n\n if (t === 'LISTO' || t === 'FINALIZAR' || t === 'PROCESAR') {\n return 'LISTO';\n }\n\n if (messageType === 'audio') return 'MEDIA_AUDIO';\n if (messageType === 'image') return 'MEDIA_IMAGEN';\n if (messageType === 'video') return 'MEDIA_VIDEO';\n\n return 'MENSAJE';\n}\n\nfunction makeEventId() {\n const msgId = clean(key.id || data.id || data.messageId || input.event_id);\n if (msgId) return msgId;\n\n return `WA-${Date.now()}-${Math.random().toString(36).slice(2, 8).toUpperCase()}`;\n}\n\nconst remoteJid = getRemoteJid();\n\nconst managerTelefono = onlyDigits(\n input.manager_telefono ||\n getPhoneFromJid(remoteJid)\n);\n\nconst managerNombre = clean(\n input.manager_nombre ||\n data.pushName ||\n data.senderName ||\n data.message?.pushName ||\n ''\n);\n\nconst texto = getTextFromMessage(message);\nconst messageType = detectMessageType(message);\nconst accionFlujo = detectAccion(texto, messageType);\n\nconst tieneMedia = ['image', 'video', 'audio', 'document'].includes(messageType);\n\nconst rawPreview = JSON.stringify(body).slice(0, 1500);\n\nreturn {\n json: {\n event_id: makeEventId(),\n fecha_recepcion: new Date().toISOString(),\n\n canal_origen: clean(input.canal_origen || 'WHATSAPP'),\n\n manager_telefono: managerTelefono,\n manager_nombre: managerNombre,\n usuario_id_origen: managerTelefono,\n\n remote_jid: remoteJid,\n from_me: Boolean(input.from_me ?? key.fromMe ?? data.fromMe ?? false),\n\n message_type: messageType,\n texto,\n accion_flujo: accionFlujo,\n\n tiene_media: tieneMedia,\n media_count: tieneMedia ? 1 : 0,\n\n raw_preview: rawPreview,\n raw_event: body,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5360, -912 ], "id": "283af502-8a49-4326-ac49-71d1efa1f8b8", "name": "Code - Normalizar evento WhatsApp" }, { "parameters": { "respondWith": "json", "responseBody": "={{\n {\n ok: true,\n received: true,\n event_id: $json.event_id\n }\n}}", "options": {} }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.5, "position": [ -5152, -912 ], "id": "6f489838-bbfa-4f25-a16c-9786cc2b598b", "name": "Respond - OK Evolution" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "f4d8feac-ea04-4689-806a-42d4e97d451b", "leftValue": "={{ $json.from_me }}", "rightValue": "", "operator": { "type": "boolean", "operation": "false", "singleValue": true } }, { "id": "758ddbe7-3ec0-4a00-8812-7fcad7c3767d", "leftValue": "={{ $json.manager_telefono }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -4944, -912 ], "id": "9116ea58-e049-4c43-80e1-3feb04d34117", "name": "IF - Mensaje entrante válido" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nconst textoFormato = `Para reportar una propuesta ejecutada, envía la información así:\n\nEJECUTADA\nPropuesta: nombre o enlace de la propuesta\nMarca/Cliente:\nPaís:\nUbicación:\nFecha de ejecución:\nComentario:\n\nLuego envía las fotos de la ejecución.\n\nCuando termines, escribe: LISTO\n\nImportante: envía una propuesta ejecutada a la vez. Cuando termines, escribe LISTO antes de iniciar otro reporte.`;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5920, 1808 ], "id": "b810d86a-8394-4f0c-8f37-249d19b530fd", "name": "Code - Preparar formato WhatsApp" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "={{ $json.texto }}", "comando": "={{ $json.comando }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "=PENDIENTE" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -6272, 4144 ], "id": "4861734d-ae45-4717-ada0-c93f78c6e7ab", "name": "Sheets - Guardar evento WhatsApp", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nconst texto = `Recibido. Puedes enviar más fotos o información de la propuesta ejecutada.\n\nCuando termines, escribe: LISTO`;\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: managerTelefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6064, 4144 ], "id": "cff92511-3c01-4740-abf9-1da7bd3e9dfc", "name": "Code - Preparar confirmación recibido" }, { "parameters": { "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nlet texto;\n\nif ($json.estado_revision === 'REQUIERE_REVISION') {\n texto = `Recibí tu solicitud para procesar la propuesta ejecutada, pero hay información que debemos revisar:\n\n${$json.motivo_revision}\n\nPuedes enviar la información faltante y luego escribir LISTO nuevamente.`;\n} else {\n texto = `Perfecto. Recibí la información de la propuesta ejecutada.\n\nEventos recibidos: ${$json.eventos_pendientes_count}\nFotos: ${$json.fotos_count}\nVideos: ${$json.videos_count}\nAudios: ${$json.audios_count}\n\nEn la próxima fase el sistema analizará la información, guardará los archivos y generará el registro correspondiente.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: managerTelefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5824, 2944 ], "id": "e9efaed0-1b16-4461-b5de-9baeda971da8", "name": "Code - Preparar respuesta LISTO" }, { "parameters": { "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -8240, 2512 ], "id": "d87536bf-f92d-47dd-b6cf-c209a9e9ce16", "name": "Sheets - Leer eventos pendientes", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const rows = $input.all();\n\nconst telefonoActual = String(\n $('Code - Normalizar evento WhatsApp').first().json.manager_telefono || ''\n).replace(/\\D/g, '');\n\nconst managerNombreActual =\n $('Code - Normalizar evento WhatsApp').first().json.manager_nombre || '';\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nfunction extractField(text, label) {\n const regex = new RegExp(`${label}\\\\s*:\\\\s*(.+)`, 'i');\n const match = clean(text).match(regex);\n return match ? clean(match[1]) : '';\n}\n\nconst eventos = rows\n .map(item => item.json || {})\n .filter(row => {\n const tel = String(row.manager_telefono || '').replace(/\\D/g, '');\n const estado = norm(row.estado || 'PENDIENTE');\n return tel === telefonoActual && estado === 'PENDIENTE';\n });\n\nconst textos = eventos\n .map(e => clean(e.texto))\n .filter(Boolean);\n\nconst textoCompleto = textos.join('\\n\\n');\n\nconst fotosCount = eventos.filter(e => norm(e.message_type) === 'IMAGE').length;\nconst videosCount = eventos.filter(e => norm(e.message_type) === 'VIDEO').length;\nconst audiosCount = eventos.filter(e => norm(e.message_type) === 'AUDIO').length;\n\nconst propuestaReferencia =\n extractField(textoCompleto, 'Propuesta') ||\n extractField(textoCompleto, 'Propuesta ejecutada');\n\nconst marcaCliente =\n extractField(textoCompleto, 'Marca/Cliente') ||\n extractField(textoCompleto, 'Marca') ||\n extractField(textoCompleto, 'Cliente');\n\nconst pais = extractField(textoCompleto, 'País') || extractField(textoCompleto, 'Pais');\nconst ubicacion = extractField(textoCompleto, 'Ubicación') || extractField(textoCompleto, 'Ubicacion');\nconst fechaEjecucion =\n extractField(textoCompleto, 'Fecha de ejecución') ||\n extractField(textoCompleto, 'Fecha ejecucion') ||\n extractField(textoCompleto, 'Fecha');\n\nconst comentario = extractField(textoCompleto, 'Comentario') || textoCompleto;\n\nconst now = new Date();\nconst fechaISO = now.toISOString();\n\nconst ejecucionId = `EJEC-${fechaISO.slice(0, 10).replace(/-/g, '')}-${telefonoActual.slice(-4)}-${Math.random().toString(36).slice(2, 6).toUpperCase()}`;\n\nconst motivosRevision = [];\n\nif (!eventos.length) motivosRevision.push('No se encontraron eventos pendientes para este número.');\nif (!propuestaReferencia) motivosRevision.push('Falta nombre o enlace de la propuesta.');\nif (!marcaCliente) motivosRevision.push('Falta marca o cliente.');\nif (!pais) motivosRevision.push('Falta país.');\nif (!ubicacion) motivosRevision.push('Falta ubicación.');\nif (fotosCount === 0 && videosCount === 0 && audiosCount === 0) {\n motivosRevision.push('No se detectó media en la sesión pendiente.');\n}\n\nconst estadoRevision = motivosRevision.length ? 'REQUIERE_REVISION' : 'PENDIENTE_PROCESAR';\n\nreturn [\n {\n json: {\n ejecucion_id: ejecucionId,\n fecha_recepcion: fechaISO,\n fecha_ejecucion: fechaEjecucion,\n manager_nombre: managerNombreActual,\n manager_telefono: telefonoActual,\n\n propuesta_referencia: propuestaReferencia,\n marca_cliente: marcaCliente,\n pais,\n ubicacion,\n comentario_original: comentario,\n\n eventos_pendientes_count: eventos.length,\n fotos_count: fotosCount,\n videos_count: videosCount,\n audios_count: audiosCount,\n\n estado_revision: estadoRevision,\n motivo_revision: motivosRevision.join(' | '),\n\n texto_sesion: textoCompleto,\n eventos_sesion: eventos,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -8000, 2512 ], "id": "5bbf52ff-dcd2-49b4-80e1-5e48980cda28", "name": "Code - Consolidar sesión LISTO" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "4425ec41-389a-45cf-8454-e54ab9168298", "leftValue": "={{ $json.estado_revision }}", "rightValue": "PENDIENTE_PROCESAR", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -7776, 2512 ], "id": "7b3ca15d-d4a9-4788-ae1e-2dc833cc5036", "name": "IF - Sesión lista para procesar" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "function clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction slug(value, max = 50) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toUpperCase()\n .slice(0, max);\n}\n\nfunction paisCorto(value) {\n const p = slug(value, 40);\n\n const mapa = {\n 'REPUBLICA-DOMINICANA': 'RD',\n 'DOMINICANA': 'RD',\n 'PANAMA': 'PA',\n 'GUATEMALA': 'GT',\n 'COSTA-RICA': 'CR',\n 'EL-SALVADOR': 'SV',\n 'HONDURAS': 'HN',\n 'NICARAGUA': 'NI',\n 'COLOMBIA': 'CO',\n 'MEXICO': 'MX',\n 'PUERTO-RICO': 'PR',\n };\n\n return mapa[p] || p || 'SIN-PAIS';\n}\n\nconst fechaRaw = clean($json.fecha_ejecucion) || new Date().toISOString().slice(0, 10);\nconst fechaCompacta = fechaRaw.replace(/\\D/g, '').slice(0, 8) || new Date().toISOString().slice(0, 10).replace(/-/g, '');\n\nconst pais = paisCorto($json.pais);\n\nconst marcaCliente = slug($json.marca_cliente || $json.marca || $json.cliente || 'SIN-MARCA', 35);\n\nconst proyecto = slug(\n $json.propuesta_referencia ||\n $json.propuesta_nombre_banco ||\n $json.comentario_original ||\n 'SIN-PROYECTO',\n 45\n);\n\nconst telefono4 = clean($json.manager_telefono).replace(/\\D/g, '').slice(-4) || '0000';\n\nconst baseName = `EJEC_${fechaCompacta}_${pais}_${marcaCliente}_${proyecto}_${telefono4}`;\n\nreturn {\n json: {\n ...$json,\n drive_folder_name: baseName,\n presentation_file_name: `${baseName} - Reporte propuesta ejecutada`,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -7168, 2368 ], "id": "c68e4eac-1e0a-4e22-b290-6e8acd78f232", "name": "Code - Preparar carpeta ejecución" }, { "parameters": { "resource": "folder", "name": "={{ $json.drive_folder_name }}", "driveId": { "__rl": true, "mode": "list", "value": "My Drive" }, "folderId": { "__rl": true, "value": "16b9efHlPm0GjXaY0dYomtTU1GPu23VrU", "mode": "list", "cachedResultName": "Presentaciones de propuestas ejecutadas", "cachedResultUrl": "https://drive.google.com/drive/folders/16b9efHlPm0GjXaY0dYomtTU1GPu23VrU" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [ -6960, 2368 ], "id": "b08544bd-60d7-4eea-8669-0bc612c2615e", "name": "Drive - Crear carpeta ejecución", "credentials": { "googleDriveOAuth2Api": { "id": "g23xdGLZRzBGqKgH", "name": "Isaac - Google Drive" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Consolidar sesión LISTO').first().json;\n\nconst prompt = `\nAnaliza esta información de una propuesta ejecutada.\n\nDebes responder únicamente en JSON válido, sin markdown y sin texto adicional.\n\nDatos disponibles:\n- Ejecución ID: ${sesion.ejecucion_id}\n- Manager: ${sesion.manager_nombre}\n- Teléfono: ${sesion.manager_telefono}\n- Propuesta referencia: ${sesion.propuesta_referencia}\n- Marca/Cliente: ${sesion.marca_cliente}\n- País: ${sesion.pais}\n- Ubicación: ${sesion.ubicacion}\n- Fecha ejecución: ${sesion.fecha_ejecucion}\n- Comentario original: ${sesion.comentario_original}\n- Texto completo de sesión:\n${sesion.texto_sesion}\n\nDevuelve este JSON:\n{\n \"resumen_ia\": \"\",\n \"descripcion_ejecucion\": \"\",\n \"elementos_detectados\": \"\",\n \"tags\": \"\",\n \"cliente\": \"\",\n \"marca\": \"\",\n \"estado_revision_sugerido\": \"\",\n \"motivo_revision_sugerido\": \"\"\n}\n\nReglas:\n- No inventes datos que no estén en el texto.\n- Si no puedes separar cliente y marca, coloca el mismo valor inferido en ambos o deja vacío el campo que no sepas.\n- Los tags deben ser palabras o frases cortas separadas por coma.\n- estado_revision_sugerido debe ser \"OK\" si la información parece suficiente o \"REQUIERE_REVISION\" si faltan datos importantes.\n`;\n\nreturn {\n json: {\n ...sesion,\n prompt_analisis_ia: prompt,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6752, 2368 ], "id": "3c073b69-252b-49ce-afcc-60fa3a66adbc", "name": "Code - Preparar análisis IA ejecución" }, { "parameters": { "modelId": { "__rl": true, "value": "models/gemini-2.5-flash-lite", "mode": "list", "cachedResultName": "models/gemini-2.5-flash-lite" }, "messages": { "values": [ { "content": "={{ $json.prompt_analisis_ia }}" } ] }, "builtInTools": {}, "options": {} }, "type": "@n8n/n8n-nodes-langchain.googleGemini", "typeVersion": 1.1, "position": [ -6544, 2368 ], "id": "f3e052ac-db7e-46d9-b4f2-8fb1199b1274", "name": "Gemini - Analizar texto ejecución", "credentials": { "googlePalmApi": { "id": "jvsXYwL6IOoY2DBU", "name": "Isaac - Gemini Api Pago" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Consolidar sesión LISTO').first().json;\nconst drive = $('Drive - Crear carpeta ejecución').first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction parseAI(value) {\n const raw = clean(value);\n\n if (!raw) return {};\n\n try {\n return JSON.parse(raw);\n } catch (e) {\n const match = raw.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n try {\n return JSON.parse(match[0]);\n } catch (err) {}\n }\n }\n\n return {\n resumen_ia: raw,\n };\n}\n\nconst rawAI =\n $json.output ||\n $json.text ||\n $json.response ||\n $json.content ||\n $json.message ||\n '';\n\nconst ai = parseAI(rawAI);\n\nconst driveId = clean(drive.id);\nconst mediaFolderUrl =\n clean(drive.webViewLink) ||\n clean(drive.webUrl) ||\n (driveId ? `https://drive.google.com/drive/folders/${driveId}` : 'PENDIENTE');\n\nconst estadoRevisionIA = clean(ai.estado_revision_sugerido);\nconst motivoRevisionIA = clean(ai.motivo_revision_sugerido);\n\nconst estadoRevision =\n estadoRevisionIA ||\n sesion.estado_revision ||\n 'PENDIENTE';\n\nconst motivoRevision =\n motivoRevisionIA ||\n sesion.motivo_revision ||\n '';\n\nreturn {\n json: {\n ejecucion_id: sesion.ejecucion_id,\n fecha_recepcion: sesion.fecha_recepcion,\n fecha_ejecucion: sesion.fecha_ejecucion,\n\n manager_nombre: sesion.manager_nombre,\n manager_telefono: sesion.manager_telefono,\n\n propuesta_referencia: sesion.propuesta_referencia,\n\n propuesta_match_estado: 'PENDIENTE_MATCH',\n propuesta_match_confianza: '',\n propuesta_nombre_banco: '',\n propuesta_link_banco: '',\n\n marca: clean(ai.marca) || sesion.marca_cliente,\n cliente: clean(ai.cliente) || sesion.marca_cliente,\n pais: sesion.pais,\n ubicacion: sesion.ubicacion,\n\n comentario_original: sesion.comentario_original,\n\n resumen_ia: clean(ai.resumen_ia) || 'PENDIENTE',\n descripcion_ejecucion: clean(ai.descripcion_ejecucion) || 'PENDIENTE',\n elementos_detectados: clean(ai.elementos_detectados) || 'PENDIENTE',\n tags: clean(ai.tags) || 'PENDIENTE',\n\n media_folder_url: mediaFolderUrl,\n presentacion_ejecucion_url: 'PENDIENTE',\n\n fotos_count: sesion.fotos_count,\n videos_count: sesion.videos_count,\n audios_count: sesion.audios_count,\n\n estado_revision: estadoRevision,\n motivo_revision: motivoRevision,\n ultima_actualizacion: new Date().toISOString(),\n\n eventos_sesion: sesion.eventos_sesion,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6192, 2368 ], "id": "6890a893-dcf4-4ed6-acf4-ded397ec611d", "name": "Code - Preparar fila propuesta ejecutada" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 1766200759, "mode": "list", "cachedResultName": "propuestas_ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=1766200759" }, "columns": { "mappingMode": "defineBelow", "value": { "ultima_actualizacion": "={{ $json.ultima_actualizacion }}", "motivo_revision": "={{ $json.motivo_revision }}", "estado_revision": "={{ $json.estado_revision }}", "audios_count": "={{ $json.audios_count }}", "videos_count": "={{ $json.videos_count }}", "fotos_count": "={{ $json.fotos_count }}", "presentacion_ejecucion_url": "={{ $json.presentacion_ejecucion_url }}", "media_folder_url": "={{ $json.media_folder_url }}", "tags": "={{ $json.tags }}", "elementos_detectados": "={{ $json.elementos_detectados }}", "descripcion_ejecucion": "={{ $json.descripcion_ejecucion }}", "resumen_ia": "={{ $json.resumen_ia }}", "comentario_original": "={{ $json.comentario_original }}", "ubicacion": "={{ $json.ubicacion }}", "pais": "={{ $json.pais }}", "cliente": "={{ $json.cliente }}", "marca": "={{ $json.marca }}", "propuesta_link_banco": "={{ $json.propuesta_link_banco }}", "propuesta_nombre_banco": "={{ $json.propuesta_nombre_banco }}", "propuesta_match_confianza": "={{ $json.propuesta_match_confianza }}", "propuesta_match_estado": "={{ $json.propuesta_match_estado }}", "propuesta_referencia": "={{ $json.propuesta_referencia }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "fecha_ejecucion": "={{ $json.fecha_ejecucion }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "ejecucion_id": "={{ $json.ejecucion_id }}" }, "matchingColumns": [], "schema": [ { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_ejecucion", "displayName": "fecha_ejecucion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_referencia", "displayName": "propuesta_referencia", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_match_estado", "displayName": "propuesta_match_estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_match_confianza", "displayName": "propuesta_match_confianza", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_nombre_banco", "displayName": "propuesta_nombre_banco", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_link_banco", "displayName": "propuesta_link_banco", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "marca", "displayName": "marca", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "cliente", "displayName": "cliente", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "pais", "displayName": "pais", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ubicacion", "displayName": "ubicacion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comentario_original", "displayName": "comentario_original", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "resumen_ia", "displayName": "resumen_ia", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "descripcion_ejecucion", "displayName": "descripcion_ejecucion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "elementos_detectados", "displayName": "elementos_detectados", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tags", "displayName": "tags", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_folder_url", "displayName": "media_folder_url", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "presentacion_ejecucion_url", "displayName": "presentacion_ejecucion_url", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fotos_count", "displayName": "fotos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audios_count", "displayName": "audios_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado_revision", "displayName": "estado_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actualizacion", "displayName": "ultima_actualizacion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -5152, 2368 ], "id": "1c48ef9f-5d8a-4b7d-89fc-bc8374e5f05d", "name": "Sheets - Guardar propuesta ejecutada", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const filaFinal = $('Code - Preparar fila propuesta ejecutada').first().json;\nconst eventos = filaFinal.eventos_sesion || [];\n\nfunction getRowNumber(row) {\n return (\n row.row_number ||\n row.__row_number ||\n row.__rowNumber ||\n row.rowNumber ||\n row._row_number ||\n ''\n );\n}\n\nreturn eventos\n .map(evento => {\n return {\n json: {\n ...evento,\n row_number: getRowNumber(evento),\n estado: 'PROCESADO',\n ejecucion_id: filaFinal.ejecucion_id,\n fecha_procesado: new Date().toISOString(),\n },\n };\n })\n .filter(item => item.json.row_number);" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -4944, 2368 ], "id": "8b159c83-3b1b-4a0d-b6c6-fcb34fa2ec7b", "name": "Code - Preparar eventos para marcar procesados" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "estado": "={{ $json.estado }}", "ejecucion_id": "={{ $json.ejecucion_id }}", "fecha_procesado": "={{ $json.fecha_procesado }}" }, "matchingColumns": [ "event_id" ], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -4736, 2368 ], "id": "89a53ce1-73d1-44d2-a229-1a659b2b89b6", "name": "Sheets - Marcar eventos procesados", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const fila = $('Code - Preparar fila propuesta ejecutada').first().json;\n\nconst texto = `Listo. Registré la propuesta ejecutada.\n\nID: ${fila.ejecucion_id}\nMarca/Cliente: ${fila.marca || fila.cliente || 'No disponible'}\nPaís: ${fila.pais || 'No disponible'}\nUbicación: ${fila.ubicacion || 'No disponible'}\n\nGuardé el registro para revisión y procesamiento final.`;\n\nreturn {\n json: {\n ...fila,\n whatsapp_to: String(fila.manager_telefono || '').replace(/\\D/g, ''),\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -4528, 2368 ], "id": "f536693e-a8ff-4cef-bdf3-85622fd2fe30", "name": "Code - Preparar confirmación procesado" }, { "parameters": { "method": "POST", "url": "={{'https://wsp.gomezleemarketing.com'}}/message/sendText/{{'botsoporte'}}", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "={{'C267126ABB45-4C12-B626-6BAB1833F5D7'}}" } ] }, "sendBody": true, "bodyParameters": { "parameters": [ { "name": "number", "value": "={{ String($json.whatsapp_to || '').includes('@') ? String($json.whatsapp_to) : String($json.whatsapp_to || '').replace(/\\D/g, '') + '@s.whatsapp.net' }}" }, { "name": "text", "value": "={{ $json.whatsapp_text }}" }, { "name": "delay", "value": "={{2000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 3632, 320 ], "id": "6c5ba479-a050-47c3-8675-1b21aa8df531", "name": "HTTP Request - Enviar mensaje WhatsApp" }, { "parameters": { "operation": "copy", "fileId": { "__rl": true, "value": "1oDY713ydM5ef9VkfmLPUB3st7qBYPKLU", "mode": "list", "cachedResultName": "TEMPLATE_Propuesta_Ejecutada_Fulgencio.pptx", "cachedResultUrl": "https://docs.google.com/presentation/d/1oDY713ydM5ef9VkfmLPUB3st7qBYPKLU/edit?usp=drivesdk&ouid=110013484451765346305&rtpof=true&sd=true" }, "name": "={{ $('Code - Preparar carpeta ejecución').first().json.presentation_file_name }}", "sameFolder": false, "driveId": { "__rl": true, "mode": "list", "value": "My Drive" }, "folderId": { "__rl": true, "value": "={{ $('Drive - Crear carpeta ejecución').first().json.id }}", "mode": "id" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [ -5984, 2368 ], "id": "8144a6cd-6386-4309-86a4-ce290601274d", "name": "Drive - Copiar template presentación", "credentials": { "googleDriveOAuth2Api": { "id": "g23xdGLZRzBGqKgH", "name": "Isaac - Google Drive" } } }, { "parameters": { "jsCode": "const fila = $('Code - Preparar fila propuesta ejecutada').first().json;\nconst slide = $('Drive - Copiar template presentación').first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nconst presentationId = clean(slide.id);\n\nconst presentationUrl =\n clean(slide.webViewLink) ||\n clean(slide.webUrl) ||\n (presentationId ? `https://docs.google.com/presentation/d/${presentationId}/edit` : 'PENDIENTE');\n\nconst replacements = {\n '{{EJECUCION_ID}}': fila.ejecucion_id,\n '{{FECHA_EJECUCION}}': fila.fecha_ejecucion,\n '{{MARCA}}': fila.marca,\n '{{CLIENTE}}': fila.cliente,\n '{{PAIS}}': fila.pais,\n '{{UBICACION}}': fila.ubicacion,\n '{{PROPUESTA_REFERENCIA}}': fila.propuesta_referencia,\n '{{MANAGER_NOMBRE}}': fila.manager_nombre,\n '{{RESUMEN_IA}}': fila.resumen_ia,\n '{{DESCRIPCION_EJECUCION}}': fila.descripcion_ejecucion,\n '{{ELEMENTOS_DETECTADOS}}': fila.elementos_detectados,\n '{{TAGS}}': fila.tags,\n '{{MEDIA_FOLDER_URL}}': fila.media_folder_url,\n '{{FOTOS_COUNT}}': fila.fotos_count,\n '{{VIDEOS_COUNT}}': fila.videos_count,\n '{{AUDIOS_COUNT}}': fila.audios_count,\n};\n\nconst requests = Object.entries(replacements).map(([placeholder, value]) => ({\n replaceAllText: {\n containsText: {\n text: placeholder,\n matchCase: true,\n },\n replaceText: clean(value) || 'No disponible',\n },\n}));\n\nreturn {\n json: {\n ...fila,\n presentation_id: presentationId,\n presentacion_ejecucion_url: presentationUrl,\n slides_requests: requests,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5776, 2368 ], "id": "29840388-f6b6-4ed3-85df-f2f8e8e7cc88", "name": "Code - Preparar reemplazos Slides" }, { "parameters": { "method": "POST", "url": "={{ 'https://slides.googleapis.com/v1/presentations/' + $json.presentation_id + ':batchUpdate' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "sendBody": true, "specifyBody": "json", "jsonBody": "={{\n {\n requests: $json.slides_requests\n }\n}}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -5568, 2368 ], "id": "308e9bfa-2e83-4562-b9d9-2487d923d8eb", "name": "HTTP Request - Reemplazar textos Slides", "credentials": { "googleOAuth2Api": { "id": "eHseMeH39kRcXgOF", "name": "Google account 2" } } }, { "parameters": { "jsCode": "const fila = $('Code - Preparar reemplazos Slides').first().json;\n\nreturn {\n json: {\n ...fila,\n presentacion_ejecucion_url: fila.presentacion_ejecucion_url || 'PENDIENTE',\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5360, 2368 ], "id": "0f8b0f86-efba-41a9-8f18-dded874bbf48", "name": "Code - Actualizar link presentación" }, { "parameters": { "workflowInputs": { "values": [ { "name": "phone" } ] } }, "type": "n8n-nodes-base.executeWorkflowTrigger", "typeVersion": 1.1, "position": [ -13024, 1680 ], "id": "22670bba-8de0-41fb-a9a0-6da7006f418f", "name": "When Executed by Another Workflow", "disabled": true }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $json.comando }}", "rightValue": "=FORMATO", "operator": { "type": "string", "operation": "equals" }, "id": "c749d60c-b479-42d2-ab4b-32f4ab5ddcb8" } ], "combinator": "and" }, "renameOutput": "={{ true }}" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "c46d57fa-81c0-42e4-a602-6983df1d33b1", "leftValue": "={{ $json.comando }}", "rightValue": "=LISTO", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": "={{ true }}" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "27e1a704-d8e0-442b-a9ed-28430b91429a", "leftValue": "={{ $json.comando }}", "rightValue": "=NORMAL", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": "={{ true }}" } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ -12096, 800 ], "id": "7394a82d-93af-48a3-a710-19f16cb8387c", "name": "ANTERIOR - Switch Comando WhatsApp" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $json.accion_flujo }}", "rightValue": "INICIAR", "operator": { "type": "string", "operation": "equals" }, "id": "d056529b-35e5-4b59-81ea-6390368dcc4a" } ], "combinator": "and" }, "renameOutput": true, "outputKey": "INICIAR" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "8113bb38-04a1-4272-8db8-29cb469d4404", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_AUDIO", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_AUDIO" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "2f985186-3795-4cbc-ac92-e154ade8d7d2", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_IMAGEN", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_IMAGEN" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "2e257327-485f-46c7-b718-b0b2aba3a912", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "FOTOS_LISTAS", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "FOTOS_LISTAS" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "bdfd1a30-d1b1-4072-bfda-168c912317fe", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_VIDEO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_VIDEO " }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "72090cce-6818-43ab-913e-d191b61f50a3", "leftValue": "={{ $json.accion_flujo }} ", "rightValue": "SIN_VIDEO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "SIN_VIDEO" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "6f8333ec-fc61-4c12-bf9e-24d9f21ac1be", "leftValue": "={{ $json.accion_flujo }} ", "rightValue": "LISTO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "LISTO " } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ -4688, -912 ], "id": "642adcad-1a3b-44c0-87df-102e00184731", "name": "Switch - Acción flujo guiado" }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n crear_nueva_sesion: false,\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n estado: clean(sesionActiva.estado),\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: Number(sesionActiva.videos_count || 0),\n },\n },\n ];\n}\n\nconst now = new Date().toISOString();\nconst stamp = now.replace(/\\D/g, '').slice(0, 14);\nconst telefono4 = telefono.slice(-4) || '0000';\nconst random = Math.random().toString(36).slice(2, 6).toUpperCase();\n\nconst sessionId = `SES_${stamp}_${telefono4}_${random}`;\n\nreturn [\n {\n json: {\n ...entrada,\n\n crear_nueva_sesion: true,\n\n session_id: sessionId,\n manager_telefono: telefono,\n manager_nombre: clean(entrada.manager_nombre),\n canal_origen: clean(entrada.canal_origen || 'WHATSAPP'),\n\n fecha_inicio: now,\n ultima_actividad: now,\n\n etapa: 'ESPERANDO_AUDIO',\n\n audio_count: 0,\n imagenes_count: 0,\n videos_count: 0,\n\n estado: 'ACTIVA',\n ejecucion_id: '',\n motivo_revision: '',\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1360, -3488 ], "id": "9999fa28-5ba8-47e0-906c-d0fa75c38c30", "name": "Code - Resolver inicio sesión" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1568, -3488 ], "id": "158de422-2b3f-4c03-b98e-f369a22f5944", "name": "Sheets - Leer sesiones existentes", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "b9b21561-7dbb-470f-9bae-22189a2982ad", "leftValue": "={{ $json.crear_nueva_sesion }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1152, -3488 ], "id": "f7cb468c-468a-42a1-bc81-6c7effba59e0", "name": "IF - Crear nueva sesión" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $json.session_id }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "canal_origen": "={{ $json.canal_origen }}", "fecha_inicio": "={{ $json.fecha_inicio }}", "ultima_actividad": "={{ $json.ultima_actividad }}", "etapa": "={{ $json.etapa }}", "audio_count": "={{ $json.audio_count }}", "imagenes_count": "={{ $json.imagenes_count }}", "videos_count": "={{ $json.videos_count }}", "estado": "={{ $json.estado }}", "ejecucion_id": "={{ $json.ejecucion_id }}", "motivo_revision": "={{ $json.motivo_revision }}" }, "matchingColumns": [], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -960, -3520 ], "id": "f700b469-6f13-4219-b1d4-17ef93253e40", "name": "Sheets - Crear sesión reporte", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver inicio sesión').first().json;\n\nconst nombre = String(sesion.manager_nombre || '').trim();\nconst saludo = nombre ? `¡Hola, ${nombre}!` : '¡Hola!';\n\nconst texto = `📸 *Propuestas Ejecutadas - GLM*\n\n${saludo} Bienvenido al registro de propuestas ejecutadas.\n\nEste proceso permite documentar ejecuciones reales para alimentar el banco de evidencias de Fulgencio Fumado.\n\n*Paso 1 de 3 — Nota de voz obligatoria*\n\nEnvía una nota de voz indicando:\n\n• Nombre o referencia de la propuesta ejecutada\n• Marca o cliente\n• País\n• Ubicación de la ejecución\n• Fecha de ejecución\n• Qué se implementó\n• Comentarios o resultados observados\n\nImportante: registra una sola propuesta ejecutada a la vez.`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -784, -3520 ], "id": "7e6f9feb-27d7-48c1-9e0f-ae7991b910ba", "name": "Code - Preparar bienvenida y solicitud audio" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const etapa = String($json.etapa || '').trim();\n\nconst instrucciones = {\n ESPERANDO_AUDIO: 'Actualmente estoy esperando la nota de voz obligatoria.',\n ESPERANDO_IMAGENES: 'Actualmente estoy esperando las imágenes obligatorias de la ejecución.',\n ESPERANDO_VIDEO: 'Actualmente estoy esperando videos opcionales o la confirmación SIN VIDEO.',\n PROCESANDO: 'Tu reporte se encuentra en procesamiento.',\n};\n\nconst detalle =\n instrucciones[etapa] ||\n 'Tienes un reporte activo pendiente de completar.';\n\nconst texto = `⚠️ Ya tienes un reporte de propuesta ejecutada en proceso.\n\n${detalle}\n\nCompleta ese reporte antes de iniciar uno nuevo. Si deseas cancelarlo, escribe: CANCELAR`;\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -784, -3280 ], "id": "1e0e2b10-1771-4396-b11d-2e20a94a90c0", "name": "Code - Preparar aviso sesión activa" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1568, -2896 ], "id": "116153fc-b38b-4f5d-91e4-1e2576748474", "name": "Sheets - Leer sesiones para audio", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n audio_aceptado: false,\n motivo_audio: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_AUDIO') {\n return [\n {\n json: {\n ...entrada,\n audio_aceptado: false,\n motivo_audio: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst audioCountActual = Number(sesionActiva.audio_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n audio_aceptado: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_AUDIO',\n etapa: 'ESPERANDO_AUDIO',\n nueva_etapa: 'ESPERANDO_IMAGENES',\n\n audio_count: audioCountActual + 1,\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1360, -2896 ], "id": "876056a4-7a73-404d-9918-fa2e554ac686", "name": "Code - Resolver sesión para audio" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "dd1bbbb7-a9de-4214-b4a7-7d105803dc3f", "leftValue": "={{ $json.audio_aceptado }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1152, -2896 ], "id": "660d9910-164d-4a9d-b5f1-08f122a2ecaf", "name": "IF - Audio válido para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_audio === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `✅ Ya recibí la nota de voz de tu reporte.\n\nAhora debes enviar al menos una imagen de la ejecución.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ La nota de voz y las imágenes ya fueron recibidas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ Recibí tu nota de voz, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -944, -2800 ], "id": "cac36da7-8a8d-4e8f-a613-c7ad0634fb1b", "name": "Code - Preparar rechazo audio" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "NOTA DE VOZ RECIBIDA", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "fecha_procesado": "=", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -944, -2992 ], "id": "856a2aeb-dce1-46e5-99a7-dea5ac0bfd6a", "name": "Sheets - Guardar evento audio", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para audio').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para audio').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para audio').first().json.nueva_etapa }}", "audio_count": "={{ $('Code - Resolver sesión para audio').first().json.audio_count }}", "estado": "={{ $('Code - Resolver sesión para audio').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -736, -2992 ], "id": "411112c3-733c-45e0-8aa3-898fd9df589c", "name": "Sheets - Actualizar sesión tras audio", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para audio').first().json;\n\nconst texto = `✅ Nota de voz recibida.\n\n*Paso 2 de 3 — Imágenes obligatorias*\n\nAhora envía al menos una foto de la propuesta ejecutada.\n\nPuedes enviar varias imágenes seguidas.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -528, -2992 ], "id": "038cb41c-11e0-46d0-8a16-b43042ca18c8", "name": "Code - Preparar solicitud imágenes" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1680, -2432 ], "id": "843023af-78e4-4998-a71c-36fa15d2eb9e", "name": "Sheets - Leer sesiones para imagen", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n imagen_aceptada: false,\n motivo_imagen: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_IMAGENES') {\n return [\n {\n json: {\n ...entrada,\n imagen_aceptada: false,\n motivo_imagen: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst imagenesCountActual = Number(sesionActiva.imagenes_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n imagen_aceptada: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_IMAGENES',\n etapa: 'ESPERANDO_IMAGENES',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: imagenesCountActual + 1,\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1472, -2432 ], "id": "6ade68a0-6bdb-48ca-87bb-7255130e19a9", "name": "Code - Resolver sesión para imagen" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "daee475e-88ff-4d39-9823-17bd9d13435f", "leftValue": "={{ $json.imagen_aceptada }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1264, -2432 ], "id": "30ae3263-566e-4bf5-b34f-8140f246b4ff", "name": "IF - Imagen válida para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_imagen === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Antes de enviar imágenes, debes enviar la nota de voz obligatoria del reporte.\n\nIndica en la nota de voz la propuesta ejecutada, marca o cliente, país, ubicación, fecha y detalles de la ejecución.`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ Las imágenes de tu reporte ya fueron registradas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ Recibí tu imagen, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1056, -2336 ], "id": "8edb8bcb-0ecc-420e-8689-1fe387951c38", "name": "Code - Preparar rechazo imagen" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "IMAGEN RECIBIDA", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -928, -2576 ], "id": "94c6d84e-30d9-43f4-9490-3668f696368e", "name": "Sheets - Guardar evento imagen", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para imagen').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para imagen').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para imagen').first().json.etapa }}", "imagenes_count": "={{ $('Code - Resolver sesión para imagen').first().json.imagenes_count }}", "estado": "={{ $('Code - Resolver sesión para imagen').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -720, -2576 ], "id": "a66f3712-5271-4cf4-804b-fb6a831ebd42", "name": "Sheets - Actualizar sesión tras imagen", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para imagen').first().json;\nconst cantidad = Number(sesion.imagenes_count || 1);\n\nconst texto = `✅ Imagen recibida. Total de imágenes registradas: ${cantidad}.\n\nPuedes enviar más imágenes de esta ejecución.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -544, -2576 ], "id": "9464c819-ef75-4d59-bc3d-772b2fca0d28", "name": "Code - Preparar confirmación imagen recibida" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1840, -1936 ], "id": "a34138fa-0362-4231-a844-5ab2da4c5c5d", "name": "Sheets - Leer sesiones para fotos listas", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\nconst imagenesCount = Number(sesionActiva.imagenes_count || 0);\n\nif (etapaActual !== 'ESPERANDO_IMAGENES') {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (imagenesCount < 1) {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'SIN_IMAGENES',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nreturn [\n {\n json: {\n ...entrada,\n\n fotos_listas_valido: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa: clean(sesionActiva.etapa),\n nueva_etapa: 'ESPERANDO_VIDEO',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: imagenesCount,\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1632, -1936 ], "id": "f5bb8bd9-e4f5-4d2b-b430-4bede17eb178", "name": "Code - Validar fotos listas" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "67809c33-d2b5-4c2a-b551-fac585b1d0a3", "leftValue": "={{ $json.fotos_listas_valido }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1424, -1936 ], "id": "7f6752d1-49c6-41cd-b763-ff7bd4de8771", "name": "IF - Puede pasar a videos" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_fotos_listas === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.motivo_fotos_listas === 'SIN_IMAGENES') {\n texto = `⚠️ Aún no he recibido imágenes para este reporte.\n\nDebes enviar al menos una foto de la propuesta ejecutada antes de escribir FOTOS LISTAS.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Aún falta la nota de voz obligatoria.\n\nEnvía primero la nota de voz con los datos de la propuesta ejecutada.`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ Las imágenes ya fueron confirmadas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ No puedo cerrar la etapa de imágenes en este momento.\n\nCompleta el paso pendiente del reporte antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1072, -1808 ], "id": "ba6a4eac-9317-445f-828b-265d197d08d3", "name": "Code - Preparar rechazo fotos listas" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Validar fotos listas').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Validar fotos listas').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Validar fotos listas').first().json.nueva_etapa }}", "estado": "={{ $('Code - Validar fotos listas').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1120, -2080 ], "id": "7cd59c82-a72d-4ed5-a5fd-cca7c5beb86f", "name": "Sheets - Actualizar sesión a video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Validar fotos listas').first().json;\nconst cantidad = Number(sesion.imagenes_count || 0);\n\nconst texto = `✅ Imágenes recibidas: ${cantidad}.\n\n*Paso 3 de 3 — Videos opcionales*\n\nSi tienes videos de la ejecución, envíalos ahora.\n\nCuando termines de enviar los videos, escribe: LISTO\n\nSi no tienes videos, escribe: SIN VIDEO`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -912, -2080 ], "id": "e00c5ae6-8871-4e3a-a171-3d16cbf7b6b9", "name": "Code - Preparar solicitud videos" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1856, -1504 ], "id": "fbb5a845-ec9e-4f99-a56a-cd238e021a61", "name": "Sheets - Leer sesiones para video", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n video_aceptado: false,\n motivo_video: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_VIDEO') {\n return [\n {\n json: {\n ...entrada,\n video_aceptado: false,\n motivo_video: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst videosCountActual = Number(sesionActiva.videos_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n video_aceptado: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_VIDEO',\n etapa: 'ESPERANDO_VIDEO',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: videosCountActual + 1,\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1648, -1504 ], "id": "f39c9580-7677-47aa-8ea3-ed32eb1db91b", "name": "Code - Resolver sesión para video" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "cae99e4c-7474-4480-a5b3-ab8f1092acfd", "leftValue": "={{ $json.video_aceptado }} ", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1440, -1504 ], "id": "d97ff832-f7ee-4a95-9c75-22f82331fa6c", "name": "IF - Video válido para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_video === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Antes de enviar videos, debes completar la nota de voz obligatoria del reporte.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `⚠️ Antes de enviar videos, debes enviar al menos una imagen y luego escribir: FOTOS LISTAS`;\n} else {\n texto = `⚠️ Recibí tu video, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1232, -1408 ], "id": "3fc31f53-e0c1-48f7-8963-94126d49f77f", "name": "Code - Preparar rechazo video" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "VIDEO RECIBIDO ", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1232, -1600 ], "id": "dea462c9-d2d3-44d2-ba01-8bedffbed59e", "name": "Sheets - Guardar evento video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para video').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para video').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para video').first().json.etapa }}", "videos_count": "={{ $('Code - Resolver sesión para video').first().json.videos_count }}", "estado": "={{ $('Code - Resolver sesión para video').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1024, -1600 ], "id": "3ca59033-d203-4d15-8b45-561b064ec9d8", "name": "Sheets - Actualizar sesión tras video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para video').first().json;\nconst cantidad = Number(sesion.videos_count || 1);\n\nconst texto = `✅ Video recibido. Total de videos registrados: ${cantidad}.\n\nPuedes enviar más videos de esta ejecución.\n\nCuando termines, escribe: LISTO`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -816, -1600 ], "id": "3a24461d-1537-487f-ab15-b56f8d9fb921", "name": "Code - Preparar confirmación video recibido" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -3552, -576 ], "id": "8103d2bc-660e-4b66-8628-e32e5def7369", "name": "Sheets - Leer sesiones para cierre", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst accion = norm(entrada.accion_flujo);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\nconst audioCount = Number(sesionActiva.audio_count || 0);\nconst imagenesCount = Number(sesionActiva.imagenes_count || 0);\nconst videosCount = Number(sesionActiva.videos_count || 0);\n\nif (etapaActual !== 'ESPERANDO_VIDEO') {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n audio_count: audioCount,\n imagenes_count: imagenesCount,\n videos_count: videosCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (audioCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_AUDIO',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (imagenesCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_IMAGENES',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (accion === 'LISTO' && videosCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'LISTO_SIN_VIDEO',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nreturn [\n {\n json: {\n ...entrada,\n\n cierre_valido: true,\n cierre_tipo: accion,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n audio_count: audioCount,\n imagenes_count: imagenesCount,\n videos_count: videosCount,\n\n etapa_anterior: clean(sesionActiva.etapa),\n nueva_etapa: 'PROCESANDO',\n estado_sesion: 'ACTIVA',\n ultima_actividad: now,\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -3264, -576 ], "id": "e70aac97-57e2-4cdd-aec8-4b8f7d78c595", "name": "Code - Validar cierre reporte" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "77d8e579-5dbc-429d-9f5f-5ad6bba8d32e", "leftValue": "={{ $json.cierre_valido }} ", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -3056, -576 ], "id": "a5ec7848-c6c1-40df-9d43-18367fa13d5f", "name": "If" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_cierre === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.motivo_cierre === 'SIN_AUDIO') {\n texto = `⚠️ No puedo procesar el reporte porque falta la nota de voz obligatoria.`;\n} else if ($json.motivo_cierre === 'SIN_IMAGENES') {\n texto = `⚠️ No puedo procesar el reporte porque falta al menos una imagen de la ejecución.`;\n} else if ($json.motivo_cierre === 'LISTO_SIN_VIDEO') {\n texto = `Aún no he recibido videos para este reporte.\n\nSi no tienes videos, escribe: SIN VIDEO\n\nSi tienes videos, envíalos y luego escribe: LISTO`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Primero debes enviar la nota de voz obligatoria.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `⚠️ Primero debes enviar al menos una imagen y luego escribir: FOTOS LISTAS`;\n} else {\n texto = `⚠️ Tu reporte no puede procesarse todavía porque falta completar el paso activo.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2848, -480 ], "id": "41657678-c37f-4b9f-a060-bce5d1b967d9", "name": "Code - Preparar rechazo cierre" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Validar cierre reporte').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Validar cierre reporte').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Validar cierre reporte').first().json.nueva_etapa }}", "estado": "={{ $('Code - Validar cierre reporte').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -2752, -768 ], "id": "8aad06a9-4e71-4846-a507-01d98cb38036", "name": "Sheets - Actualizar sesión a procesando", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const cierre = $('Code - Validar cierre reporte').first().json;\n\nreturn {\n json: {\n session_id: cierre.session_id,\n manager_telefono: cierre.manager_telefono,\n manager_nombre: cierre.manager_nombre,\n canal_origen: cierre.canal_origen,\n\n audio_count: cierre.audio_count,\n imagenes_count: cierre.imagenes_count,\n videos_count: cierre.videos_count,\n\n cierre_tipo: cierre.cierre_tipo,\n estado_procesamiento: 'LISTO_PARA_ANALISIS_IA',\n\n whatsapp_to: cierre.manager_telefono,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2528, -768 ], "id": "c55d3919-462f-4da3-97f8-e1dbfa0d73d2", "name": "Code - Preparar procesamiento final guiado" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -2336, -768 ], "id": "5f7d65fd-2ab0-4649-bdad-76c4d07b7921", "name": "Sheets - Leer eventos de sesión final", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const cierre = $('Code - Preparar procesamiento final guiado').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst sessionId = clean(cierre.session_id);\n\nconst eventosSesion = rows.filter(row => {\n return clean(row.session_id) === sessionId;\n});\n\nconst eventosPendientes = eventosSesion.filter(row => {\n const estado = norm(row.estado);\n return estado === 'PENDIENTE' || estado === '';\n});\n\nconst audios = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'AUDIO';\n});\n\nconst imagenes = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'IMAGE';\n});\n\nconst videos = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'VIDEO';\n});\n\nconst tieneAudio = audios.length >= 1;\nconst tieneImagenes = imagenes.length >= 1;\n\nlet motivoError = '';\n\nif (!tieneAudio) {\n motivoError = 'SIN_AUDIO_REGISTRADO';\n} else if (!tieneImagenes) {\n motivoError = 'SIN_IMAGENES_REGISTRADAS';\n}\n\nconst sesionCompleta = tieneAudio && tieneImagenes;\n\nreturn [\n {\n json: {\n ...cierre,\n\n session_id: sessionId,\n\n sesion_completa_para_analizar: sesionCompleta,\n motivo_error_sesion: motivoError,\n\n total_eventos_sesion: eventosSesion.length,\n total_eventos_pendientes: eventosPendientes.length,\n\n audio_count: audios.length,\n imagenes_count: imagenes.length,\n videos_count: videos.length,\n\n audio_event_id: audios.length ? clean(audios[0].event_id) : '',\n audio_event_ids: audios.map(row => clean(row.event_id)).filter(Boolean),\n imagen_event_ids: imagenes.map(row => clean(row.event_id)).filter(Boolean),\n video_event_ids: videos.map(row => clean(row.event_id)).filter(Boolean),\n\n eventos_audio: audios,\n eventos_imagenes: imagenes,\n eventos_video: videos,\n\n estado_procesamiento: sesionCompleta\n ? 'LISTO_PARA_RECUPERAR_MEDIA'\n : 'CAPTURA_INCOMPLETA',\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2128, -768 ], "id": "2a57e50d-6db5-45c2-90ec-9e64b6da2ccd", "name": "Code - Consolidar sesión guiada para IA" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "11d390e1-dc34-4160-83f0-5449c93d89a3", "leftValue": "={{ $json.sesion_completa_para_analizar }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1920, -768 ], "id": "3e77000f-6a11-4cba-b6ff-4d3f9adee5b5", "name": "IF - Sesión completa para analizar" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_error_sesion === 'SIN_AUDIO_REGISTRADO') {\n texto = `⚠️ No pude procesar tu reporte porque no encontré la nota de voz obligatoria registrada.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n} else if ($json.motivo_error_sesion === 'SIN_IMAGENES_REGISTRADAS') {\n texto = `⚠️ No pude procesar tu reporte porque no encontré imágenes registradas de la ejecución.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n} else {\n texto = `⚠️ Ocurrió un inconveniente al consolidar las evidencias de tu reporte.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1600, -672 ], "id": "cc847c79-3980-4a7d-a160-487c3ee33360", "name": "Code - Preparar error sesión incompleta" }, { "parameters": { "method": "POST", "url": "https://wsp.gomezleemarketing.com/chat/getBase64FromMediaMessage/botsoporte", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "={{'C267126ABB45-4C12-B626-6BAB1833F5D7'}}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{\n {\n message: {\n key: {\n id: $json.audio_event_id\n }\n },\n convertToMp4: false\n }\n}}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -1600, -960 ], "id": "074efcd5-11af-4e87-8659-cf984c78bdd8", "name": "HTTP Request - Obtener audio Evolution" } ], "connections": { "Code - Normalizar evento WhatsApp": { "main": [ [ { "node": "Respond - OK Evolution", "type": "main", "index": 0 } ] ] }, "Respond - OK Evolution": { "main": [ [ { "node": "IF - Mensaje entrante válido", "type": "main", "index": 0 } ] ] }, "IF - Mensaje entrante válido": { "main": [ [ { "node": "Switch - Acción flujo guiado", "type": "main", "index": 0 } ] ] }, "Code - Preparar formato WhatsApp": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento WhatsApp": { "main": [ [ { "node": "Code - Preparar confirmación recibido", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación recibido": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar respuesta LISTO": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer eventos pendientes": { "main": [ [ { "node": "Code - Consolidar sesión LISTO", "type": "main", "index": 0 } ] ] }, "Code - Consolidar sesión LISTO": { "main": [ [ { "node": "IF - Sesión lista para procesar", "type": "main", "index": 0 } ] ] }, "IF - Sesión lista para procesar": { "main": [ [ { "node": "Code - Preparar carpeta ejecución", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar respuesta LISTO", "type": "main", "index": 0 } ] ] }, "Code - Preparar carpeta ejecución": { "main": [ [ { "node": "Drive - Crear carpeta ejecución", "type": "main", "index": 0 } ] ] }, "Drive - Crear carpeta ejecución": { "main": [ [ { "node": "Code - Preparar análisis IA ejecución", "type": "main", "index": 0 } ] ] }, "Code - Preparar análisis IA ejecución": { "main": [ [ { "node": "Gemini - Analizar texto ejecución", "type": "main", "index": 0 } ] ] }, "Gemini - Analizar texto ejecución": { "main": [ [ { "node": "Code - Preparar fila propuesta ejecutada", "type": "main", "index": 0 } ] ] }, "Code - Preparar fila propuesta ejecutada": { "main": [ [ { "node": "Drive - Copiar template presentación", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar propuesta ejecutada": { "main": [ [ { "node": "Code - Preparar eventos para marcar procesados", "type": "main", "index": 0 } ] ] }, "Code - Preparar eventos para marcar procesados": { "main": [ [ { "node": "Sheets - Marcar eventos procesados", "type": "main", "index": 0 } ] ] }, "Sheets - Marcar eventos procesados": { "main": [ [ { "node": "Code - Preparar confirmación procesado", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación procesado": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Webhook": { "main": [ [ { "node": "Code - Normalizar evento WhatsApp", "type": "main", "index": 0 } ] ] }, "Drive - Copiar template presentación": { "main": [ [ { "node": "Code - Preparar reemplazos Slides", "type": "main", "index": 0 } ] ] }, "Code - Preparar reemplazos Slides": { "main": [ [ { "node": "HTTP Request - Reemplazar textos Slides", "type": "main", "index": 0 } ] ] }, "HTTP Request - Reemplazar textos Slides": { "main": [ [ { "node": "Code - Actualizar link presentación", "type": "main", "index": 0 } ] ] }, "Code - Actualizar link presentación": { "main": [ [ { "node": "Sheets - Guardar propuesta ejecutada", "type": "main", "index": 0 } ] ] }, "When Executed by Another Workflow": { "main": [ [] ] }, "ANTERIOR - Switch Comando WhatsApp": { "main": [ [ { "node": "Code - Preparar formato WhatsApp", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer eventos pendientes", "type": "main", "index": 0 } ], [ { "node": "Sheets - Guardar evento WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Resolver inicio sesión": { "main": [ [ { "node": "IF - Crear nueva sesión", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones existentes": { "main": [ [ { "node": "Code - Resolver inicio sesión", "type": "main", "index": 0 } ] ] }, "IF - Crear nueva sesión": { "main": [ [ { "node": "Sheets - Crear sesión reporte", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar aviso sesión activa", "type": "main", "index": 0 } ] ] }, "Sheets - Crear sesión reporte": { "main": [ [ { "node": "Code - Preparar bienvenida y solicitud audio", "type": "main", "index": 0 } ] ] }, "Code - Preparar bienvenida y solicitud audio": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar aviso sesión activa": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Switch - Acción flujo guiado": { "main": [ [ { "node": "Sheets - Leer sesiones existentes", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para audio", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para imagen", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para fotos listas", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para video", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para cierre", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para cierre", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para audio": { "main": [ [ { "node": "Code - Resolver sesión para audio", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para audio": { "main": [ [ { "node": "IF - Audio válido para sesión", "type": "main", "index": 0 } ] ] }, "IF - Audio válido para sesión": { "main": [ [ { "node": "Sheets - Guardar evento audio", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo audio", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo audio": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento audio": { "main": [ [ { "node": "Sheets - Actualizar sesión tras audio", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras audio": { "main": [ [ { "node": "Code - Preparar solicitud imágenes", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para imagen": { "main": [ [ { "node": "Code - Resolver sesión para imagen", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para imagen": { "main": [ [ { "node": "IF - Imagen válida para sesión", "type": "main", "index": 0 } ] ] }, "IF - Imagen válida para sesión": { "main": [ [ { "node": "Sheets - Guardar evento imagen", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo imagen", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo imagen": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento imagen": { "main": [ [ { "node": "Sheets - Actualizar sesión tras imagen", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras imagen": { "main": [ [ { "node": "Code - Preparar confirmación imagen recibida", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación imagen recibida": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para fotos listas": { "main": [ [ { "node": "Code - Validar fotos listas", "type": "main", "index": 0 } ] ] }, "Code - Validar fotos listas": { "main": [ [ { "node": "IF - Puede pasar a videos", "type": "main", "index": 0 } ] ] }, "IF - Puede pasar a videos": { "main": [ [ { "node": "Sheets - Actualizar sesión a video", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo fotos listas", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo fotos listas": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión a video": { "main": [ [ { "node": "Code - Preparar solicitud videos", "type": "main", "index": 0 } ] ] }, "Code - Preparar solicitud videos": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para video": { "main": [ [ { "node": "Code - Resolver sesión para video", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para video": { "main": [ [ { "node": "IF - Video válido para sesión", "type": "main", "index": 0 } ] ] }, "IF - Video válido para sesión": { "main": [ [ { "node": "Sheets - Guardar evento video", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo video", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo video": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento video": { "main": [ [ { "node": "Sheets - Actualizar sesión tras video", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras video": { "main": [ [ { "node": "Code - Preparar confirmación video recibido", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación video recibido": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar solicitud imágenes": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para cierre": { "main": [ [ { "node": "Code - Validar cierre reporte", "type": "main", "index": 0 } ] ] }, "Code - Validar cierre reporte": { "main": [ [ { "node": "If", "type": "main", "index": 0 } ] ] }, "If": { "main": [ [ { "node": "Sheets - Actualizar sesión a procesando", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo cierre", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo cierre": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión a procesando": { "main": [ [ { "node": "Code - Preparar procesamiento final guiado", "type": "main", "index": 0 } ] ] }, "Code - Preparar procesamiento final guiado": { "main": [ [ { "node": "Sheets - Leer eventos de sesión final", "type": "main", "index": 0 } ] ] }, "Sheets - Leer eventos de sesión final": { "main": [ [ { "node": "Code - Consolidar sesión guiada para IA", "type": "main", "index": 0 } ] ] }, "Code - Consolidar sesión guiada para IA": { "main": [ [ { "node": "IF - Sesión completa para analizar", "type": "main", "index": 0 } ] ] }, "IF - Sesión completa para analizar": { "main": [ [ { "node": "HTTP Request - Obtener audio Evolution", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar error sesión incompleta", "type": "main", "index": 0 } ] ] }, "Code - Preparar error sesión incompleta": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1", "binaryMode": "separate", "timeSavedMode": "fixed", "errorWorkflow": "puF4LUczoSz3hcek", "callerPolicy": "workflowsFromSameOwner", "availableInMCP": false }, "staticData": null, "meta": { "templateCredsSetupCompleted": true }, "versionId": "9593f621-8097-459c-8c53-d734fafaffe2", "activeVersionId": "9593f621-8097-459c-8c53-d734fafaffe2", "versionCounter": 529, "triggerCount": 1, "shared": [ { "updatedAt": "2026-05-23T12:05:00.160Z", "createdAt": "2026-05-23T12:05:00.160Z", "role": "workflow:owner", "workflowId": "t6lFUulNtDIR3tAm", "projectId": "PJpTANzTXIFibWsW", "project": { "updatedAt": "2026-04-22T14:25:09.686Z", "createdAt": "2026-04-22T14:22:54.790Z", "id": "PJpTANzTXIFibWsW", "name": "Isaac Aracena ", "type": "personal", "icon": null, "description": null, "creatorId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" } } ], "tags": [], "activeVersion": { "updatedAt": "2026-06-04T00:42:28.000Z", "createdAt": "2026-06-02T14:05:16.514Z", "versionId": "9593f621-8097-459c-8c53-d734fafaffe2", "workflowId": "t6lFUulNtDIR3tAm", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "6e314249-3d5f-4052-b303-0188d1da9e30", "responseMode": "responseNode", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -5584, -912 ], "id": "cd3b1b5e-bc1d-4879-bb5e-e3caa86d38c0", "name": "Webhook", "webhookId": "6e314249-3d5f-4052-b303-0188d1da9e30" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const input = $json || {};\nconst body = input.body || input;\nconst data = body.data || body;\n\nconst key =\n data.key ||\n data.message?.key ||\n input.key ||\n {};\n\nconst message =\n data.message ||\n data.messages?.[0]?.message ||\n input.message ||\n {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nfunction getRemoteJid() {\n return clean(\n input.remote_jid ||\n input.remoteJid ||\n key.remoteJid ||\n data.remoteJid ||\n data.chatId ||\n data.from ||\n data.sender ||\n ''\n );\n}\n\nfunction getPhoneFromJid(jid) {\n return onlyDigits(clean(jid).split('@')[0]);\n}\n\nfunction getTextFromMessage(msg) {\n return clean(\n input.texto ||\n input.text ||\n msg.conversation ||\n msg.extendedTextMessage?.text ||\n msg.imageMessage?.caption ||\n msg.videoMessage?.caption ||\n msg.documentMessage?.caption ||\n data.messageText ||\n data.text ||\n data.body ||\n ''\n );\n}\n\nfunction detectMessageType(msg) {\n if (input.message_type) return clean(input.message_type).toLowerCase();\n if (msg.imageMessage) return 'image';\n if (msg.videoMessage) return 'video';\n if (msg.audioMessage) return 'audio';\n if (msg.documentMessage) return 'document';\n if (msg.conversation || msg.extendedTextMessage) return 'text';\n return clean(data.messageType || data.type || 'unknown').toLowerCase();\n}\n\nfunction detectAccion(texto, messageType) {\n const t = norm(texto);\n\n const flujoDestino = norm(\n input.flujo_destino ||\n input.workflow_selected ||\n input.opcion_flujo ||\n ''\n );\n\n if (\n t === '2' ||\n t === 'INICIAR' ||\n t === 'INICIAR REPORTE' ||\n t === 'PROPUESTAS EJECUTADAS' ||\n flujoDestino.includes('PROPUESTAS EJECUTADAS') ||\n input.iniciar_flujo === true\n ) {\n return 'INICIAR';\n }\n\n if (t === 'CANCELAR' || t === 'CANCELAR REPORTE') {\n return 'CANCELAR';\n }\n\n if (t === 'FOTOS LISTAS' || t === 'IMAGENES LISTAS' || t === 'IMÁGENES LISTAS') {\n return 'FOTOS_LISTAS';\n }\n\n if (t === 'SIN VIDEO' || t === 'NO TENGO VIDEO' || t === 'NO HAY VIDEO') {\n return 'SIN_VIDEO';\n }\n\n if (t === 'LISTO' || t === 'FINALIZAR' || t === 'PROCESAR') {\n return 'LISTO';\n }\n\n if (messageType === 'audio') return 'MEDIA_AUDIO';\n if (messageType === 'image') return 'MEDIA_IMAGEN';\n if (messageType === 'video') return 'MEDIA_VIDEO';\n\n return 'MENSAJE';\n}\n\nfunction makeEventId() {\n const msgId = clean(key.id || data.id || data.messageId || input.event_id);\n if (msgId) return msgId;\n\n return `WA-${Date.now()}-${Math.random().toString(36).slice(2, 8).toUpperCase()}`;\n}\n\nconst remoteJid = getRemoteJid();\n\nconst managerTelefono = onlyDigits(\n input.manager_telefono ||\n getPhoneFromJid(remoteJid)\n);\n\nconst managerNombre = clean(\n input.manager_nombre ||\n data.pushName ||\n data.senderName ||\n data.message?.pushName ||\n ''\n);\n\nconst texto = getTextFromMessage(message);\nconst messageType = detectMessageType(message);\nconst accionFlujo = detectAccion(texto, messageType);\n\nconst tieneMedia = ['image', 'video', 'audio', 'document'].includes(messageType);\n\nconst rawPreview = JSON.stringify(body).slice(0, 1500);\n\nreturn {\n json: {\n event_id: makeEventId(),\n fecha_recepcion: new Date().toISOString(),\n\n canal_origen: clean(input.canal_origen || 'WHATSAPP'),\n\n manager_telefono: managerTelefono,\n manager_nombre: managerNombre,\n usuario_id_origen: managerTelefono,\n\n remote_jid: remoteJid,\n from_me: Boolean(input.from_me ?? key.fromMe ?? data.fromMe ?? false),\n\n message_type: messageType,\n texto,\n accion_flujo: accionFlujo,\n\n tiene_media: tieneMedia,\n media_count: tieneMedia ? 1 : 0,\n\n raw_preview: rawPreview,\n raw_event: body,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5360, -912 ], "id": "283af502-8a49-4326-ac49-71d1efa1f8b8", "name": "Code - Normalizar evento WhatsApp" }, { "parameters": { "respondWith": "json", "responseBody": "={{\n {\n ok: true,\n received: true,\n event_id: $json.event_id\n }\n}}", "options": {} }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.5, "position": [ -5152, -912 ], "id": "6f489838-bbfa-4f25-a16c-9786cc2b598b", "name": "Respond - OK Evolution" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "f4d8feac-ea04-4689-806a-42d4e97d451b", "leftValue": "={{ $json.from_me }}", "rightValue": "", "operator": { "type": "boolean", "operation": "false", "singleValue": true } }, { "id": "758ddbe7-3ec0-4a00-8812-7fcad7c3767d", "leftValue": "={{ $json.manager_telefono }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -4944, -912 ], "id": "9116ea58-e049-4c43-80e1-3feb04d34117", "name": "IF - Mensaje entrante válido" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nconst textoFormato = `Para reportar una propuesta ejecutada, envía la información así:\n\nEJECUTADA\nPropuesta: nombre o enlace de la propuesta\nMarca/Cliente:\nPaís:\nUbicación:\nFecha de ejecución:\nComentario:\n\nLuego envía las fotos de la ejecución.\n\nCuando termines, escribe: LISTO\n\nImportante: envía una propuesta ejecutada a la vez. Cuando termines, escribe LISTO antes de iniciar otro reporte.`;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5920, 1808 ], "id": "b810d86a-8394-4f0c-8f37-249d19b530fd", "name": "Code - Preparar formato WhatsApp" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "={{ $json.texto }}", "comando": "={{ $json.comando }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "=PENDIENTE" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -6272, 4144 ], "id": "4861734d-ae45-4717-ada0-c93f78c6e7ab", "name": "Sheets - Guardar evento WhatsApp", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nconst texto = `Recibido. Puedes enviar más fotos o información de la propuesta ejecutada.\n\nCuando termines, escribe: LISTO`;\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: managerTelefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6064, 4144 ], "id": "cff92511-3c01-4740-abf9-1da7bd3e9dfc", "name": "Code - Preparar confirmación recibido" }, { "parameters": { "jsCode": "const managerTelefono = String($json.manager_telefono || '').replace(/\\D/g, '');\n\nlet texto;\n\nif ($json.estado_revision === 'REQUIERE_REVISION') {\n texto = `Recibí tu solicitud para procesar la propuesta ejecutada, pero hay información que debemos revisar:\n\n${$json.motivo_revision}\n\nPuedes enviar la información faltante y luego escribir LISTO nuevamente.`;\n} else {\n texto = `Perfecto. Recibí la información de la propuesta ejecutada.\n\nEventos recibidos: ${$json.eventos_pendientes_count}\nFotos: ${$json.fotos_count}\nVideos: ${$json.videos_count}\nAudios: ${$json.audios_count}\n\nEn la próxima fase el sistema analizará la información, guardará los archivos y generará el registro correspondiente.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: managerTelefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5824, 2944 ], "id": "e9efaed0-1b16-4461-b5de-9baeda971da8", "name": "Code - Preparar respuesta LISTO" }, { "parameters": { "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -8240, 2512 ], "id": "d87536bf-f92d-47dd-b6cf-c209a9e9ce16", "name": "Sheets - Leer eventos pendientes", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const rows = $input.all();\n\nconst telefonoActual = String(\n $('Code - Normalizar evento WhatsApp').first().json.manager_telefono || ''\n).replace(/\\D/g, '');\n\nconst managerNombreActual =\n $('Code - Normalizar evento WhatsApp').first().json.manager_nombre || '';\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nfunction extractField(text, label) {\n const regex = new RegExp(`${label}\\\\s*:\\\\s*(.+)`, 'i');\n const match = clean(text).match(regex);\n return match ? clean(match[1]) : '';\n}\n\nconst eventos = rows\n .map(item => item.json || {})\n .filter(row => {\n const tel = String(row.manager_telefono || '').replace(/\\D/g, '');\n const estado = norm(row.estado || 'PENDIENTE');\n return tel === telefonoActual && estado === 'PENDIENTE';\n });\n\nconst textos = eventos\n .map(e => clean(e.texto))\n .filter(Boolean);\n\nconst textoCompleto = textos.join('\\n\\n');\n\nconst fotosCount = eventos.filter(e => norm(e.message_type) === 'IMAGE').length;\nconst videosCount = eventos.filter(e => norm(e.message_type) === 'VIDEO').length;\nconst audiosCount = eventos.filter(e => norm(e.message_type) === 'AUDIO').length;\n\nconst propuestaReferencia =\n extractField(textoCompleto, 'Propuesta') ||\n extractField(textoCompleto, 'Propuesta ejecutada');\n\nconst marcaCliente =\n extractField(textoCompleto, 'Marca/Cliente') ||\n extractField(textoCompleto, 'Marca') ||\n extractField(textoCompleto, 'Cliente');\n\nconst pais = extractField(textoCompleto, 'País') || extractField(textoCompleto, 'Pais');\nconst ubicacion = extractField(textoCompleto, 'Ubicación') || extractField(textoCompleto, 'Ubicacion');\nconst fechaEjecucion =\n extractField(textoCompleto, 'Fecha de ejecución') ||\n extractField(textoCompleto, 'Fecha ejecucion') ||\n extractField(textoCompleto, 'Fecha');\n\nconst comentario = extractField(textoCompleto, 'Comentario') || textoCompleto;\n\nconst now = new Date();\nconst fechaISO = now.toISOString();\n\nconst ejecucionId = `EJEC-${fechaISO.slice(0, 10).replace(/-/g, '')}-${telefonoActual.slice(-4)}-${Math.random().toString(36).slice(2, 6).toUpperCase()}`;\n\nconst motivosRevision = [];\n\nif (!eventos.length) motivosRevision.push('No se encontraron eventos pendientes para este número.');\nif (!propuestaReferencia) motivosRevision.push('Falta nombre o enlace de la propuesta.');\nif (!marcaCliente) motivosRevision.push('Falta marca o cliente.');\nif (!pais) motivosRevision.push('Falta país.');\nif (!ubicacion) motivosRevision.push('Falta ubicación.');\nif (fotosCount === 0 && videosCount === 0 && audiosCount === 0) {\n motivosRevision.push('No se detectó media en la sesión pendiente.');\n}\n\nconst estadoRevision = motivosRevision.length ? 'REQUIERE_REVISION' : 'PENDIENTE_PROCESAR';\n\nreturn [\n {\n json: {\n ejecucion_id: ejecucionId,\n fecha_recepcion: fechaISO,\n fecha_ejecucion: fechaEjecucion,\n manager_nombre: managerNombreActual,\n manager_telefono: telefonoActual,\n\n propuesta_referencia: propuestaReferencia,\n marca_cliente: marcaCliente,\n pais,\n ubicacion,\n comentario_original: comentario,\n\n eventos_pendientes_count: eventos.length,\n fotos_count: fotosCount,\n videos_count: videosCount,\n audios_count: audiosCount,\n\n estado_revision: estadoRevision,\n motivo_revision: motivosRevision.join(' | '),\n\n texto_sesion: textoCompleto,\n eventos_sesion: eventos,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -8000, 2512 ], "id": "5bbf52ff-dcd2-49b4-80e1-5e48980cda28", "name": "Code - Consolidar sesión LISTO" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "4425ec41-389a-45cf-8454-e54ab9168298", "leftValue": "={{ $json.estado_revision }}", "rightValue": "PENDIENTE_PROCESAR", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -7776, 2512 ], "id": "7b3ca15d-d4a9-4788-ae1e-2dc833cc5036", "name": "IF - Sesión lista para procesar" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "function clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction slug(value, max = 50) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toUpperCase()\n .slice(0, max);\n}\n\nfunction paisCorto(value) {\n const p = slug(value, 40);\n\n const mapa = {\n 'REPUBLICA-DOMINICANA': 'RD',\n 'DOMINICANA': 'RD',\n 'PANAMA': 'PA',\n 'GUATEMALA': 'GT',\n 'COSTA-RICA': 'CR',\n 'EL-SALVADOR': 'SV',\n 'HONDURAS': 'HN',\n 'NICARAGUA': 'NI',\n 'COLOMBIA': 'CO',\n 'MEXICO': 'MX',\n 'PUERTO-RICO': 'PR',\n };\n\n return mapa[p] || p || 'SIN-PAIS';\n}\n\nconst fechaRaw = clean($json.fecha_ejecucion) || new Date().toISOString().slice(0, 10);\nconst fechaCompacta = fechaRaw.replace(/\\D/g, '').slice(0, 8) || new Date().toISOString().slice(0, 10).replace(/-/g, '');\n\nconst pais = paisCorto($json.pais);\n\nconst marcaCliente = slug($json.marca_cliente || $json.marca || $json.cliente || 'SIN-MARCA', 35);\n\nconst proyecto = slug(\n $json.propuesta_referencia ||\n $json.propuesta_nombre_banco ||\n $json.comentario_original ||\n 'SIN-PROYECTO',\n 45\n);\n\nconst telefono4 = clean($json.manager_telefono).replace(/\\D/g, '').slice(-4) || '0000';\n\nconst baseName = `EJEC_${fechaCompacta}_${pais}_${marcaCliente}_${proyecto}_${telefono4}`;\n\nreturn {\n json: {\n ...$json,\n drive_folder_name: baseName,\n presentation_file_name: `${baseName} - Reporte propuesta ejecutada`,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -7168, 2368 ], "id": "c68e4eac-1e0a-4e22-b290-6e8acd78f232", "name": "Code - Preparar carpeta ejecución" }, { "parameters": { "resource": "folder", "name": "={{ $json.drive_folder_name }}", "driveId": { "__rl": true, "mode": "list", "value": "My Drive" }, "folderId": { "__rl": true, "value": "16b9efHlPm0GjXaY0dYomtTU1GPu23VrU", "mode": "list", "cachedResultName": "Presentaciones de propuestas ejecutadas", "cachedResultUrl": "https://drive.google.com/drive/folders/16b9efHlPm0GjXaY0dYomtTU1GPu23VrU" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [ -6960, 2368 ], "id": "b08544bd-60d7-4eea-8669-0bc612c2615e", "name": "Drive - Crear carpeta ejecución", "credentials": { "googleDriveOAuth2Api": { "id": "g23xdGLZRzBGqKgH", "name": "Isaac - Google Drive" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Consolidar sesión LISTO').first().json;\n\nconst prompt = `\nAnaliza esta información de una propuesta ejecutada.\n\nDebes responder únicamente en JSON válido, sin markdown y sin texto adicional.\n\nDatos disponibles:\n- Ejecución ID: ${sesion.ejecucion_id}\n- Manager: ${sesion.manager_nombre}\n- Teléfono: ${sesion.manager_telefono}\n- Propuesta referencia: ${sesion.propuesta_referencia}\n- Marca/Cliente: ${sesion.marca_cliente}\n- País: ${sesion.pais}\n- Ubicación: ${sesion.ubicacion}\n- Fecha ejecución: ${sesion.fecha_ejecucion}\n- Comentario original: ${sesion.comentario_original}\n- Texto completo de sesión:\n${sesion.texto_sesion}\n\nDevuelve este JSON:\n{\n \"resumen_ia\": \"\",\n \"descripcion_ejecucion\": \"\",\n \"elementos_detectados\": \"\",\n \"tags\": \"\",\n \"cliente\": \"\",\n \"marca\": \"\",\n \"estado_revision_sugerido\": \"\",\n \"motivo_revision_sugerido\": \"\"\n}\n\nReglas:\n- No inventes datos que no estén en el texto.\n- Si no puedes separar cliente y marca, coloca el mismo valor inferido en ambos o deja vacío el campo que no sepas.\n- Los tags deben ser palabras o frases cortas separadas por coma.\n- estado_revision_sugerido debe ser \"OK\" si la información parece suficiente o \"REQUIERE_REVISION\" si faltan datos importantes.\n`;\n\nreturn {\n json: {\n ...sesion,\n prompt_analisis_ia: prompt,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6752, 2368 ], "id": "3c073b69-252b-49ce-afcc-60fa3a66adbc", "name": "Code - Preparar análisis IA ejecución" }, { "parameters": { "modelId": { "__rl": true, "value": "models/gemini-2.5-flash-lite", "mode": "list", "cachedResultName": "models/gemini-2.5-flash-lite" }, "messages": { "values": [ { "content": "={{ $json.prompt_analisis_ia }}" } ] }, "builtInTools": {}, "options": {} }, "type": "@n8n/n8n-nodes-langchain.googleGemini", "typeVersion": 1.1, "position": [ -6544, 2368 ], "id": "f3e052ac-db7e-46d9-b4f2-8fb1199b1274", "name": "Gemini - Analizar texto ejecución", "credentials": { "googlePalmApi": { "id": "jvsXYwL6IOoY2DBU", "name": "Isaac - Gemini Api Pago" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Consolidar sesión LISTO').first().json;\nconst drive = $('Drive - Crear carpeta ejecución').first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction parseAI(value) {\n const raw = clean(value);\n\n if (!raw) return {};\n\n try {\n return JSON.parse(raw);\n } catch (e) {\n const match = raw.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n try {\n return JSON.parse(match[0]);\n } catch (err) {}\n }\n }\n\n return {\n resumen_ia: raw,\n };\n}\n\nconst rawAI =\n $json.output ||\n $json.text ||\n $json.response ||\n $json.content ||\n $json.message ||\n '';\n\nconst ai = parseAI(rawAI);\n\nconst driveId = clean(drive.id);\nconst mediaFolderUrl =\n clean(drive.webViewLink) ||\n clean(drive.webUrl) ||\n (driveId ? `https://drive.google.com/drive/folders/${driveId}` : 'PENDIENTE');\n\nconst estadoRevisionIA = clean(ai.estado_revision_sugerido);\nconst motivoRevisionIA = clean(ai.motivo_revision_sugerido);\n\nconst estadoRevision =\n estadoRevisionIA ||\n sesion.estado_revision ||\n 'PENDIENTE';\n\nconst motivoRevision =\n motivoRevisionIA ||\n sesion.motivo_revision ||\n '';\n\nreturn {\n json: {\n ejecucion_id: sesion.ejecucion_id,\n fecha_recepcion: sesion.fecha_recepcion,\n fecha_ejecucion: sesion.fecha_ejecucion,\n\n manager_nombre: sesion.manager_nombre,\n manager_telefono: sesion.manager_telefono,\n\n propuesta_referencia: sesion.propuesta_referencia,\n\n propuesta_match_estado: 'PENDIENTE_MATCH',\n propuesta_match_confianza: '',\n propuesta_nombre_banco: '',\n propuesta_link_banco: '',\n\n marca: clean(ai.marca) || sesion.marca_cliente,\n cliente: clean(ai.cliente) || sesion.marca_cliente,\n pais: sesion.pais,\n ubicacion: sesion.ubicacion,\n\n comentario_original: sesion.comentario_original,\n\n resumen_ia: clean(ai.resumen_ia) || 'PENDIENTE',\n descripcion_ejecucion: clean(ai.descripcion_ejecucion) || 'PENDIENTE',\n elementos_detectados: clean(ai.elementos_detectados) || 'PENDIENTE',\n tags: clean(ai.tags) || 'PENDIENTE',\n\n media_folder_url: mediaFolderUrl,\n presentacion_ejecucion_url: 'PENDIENTE',\n\n fotos_count: sesion.fotos_count,\n videos_count: sesion.videos_count,\n audios_count: sesion.audios_count,\n\n estado_revision: estadoRevision,\n motivo_revision: motivoRevision,\n ultima_actualizacion: new Date().toISOString(),\n\n eventos_sesion: sesion.eventos_sesion,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -6192, 2368 ], "id": "6890a893-dcf4-4ed6-acf4-ded397ec611d", "name": "Code - Preparar fila propuesta ejecutada" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 1766200759, "mode": "list", "cachedResultName": "propuestas_ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=1766200759" }, "columns": { "mappingMode": "defineBelow", "value": { "ultima_actualizacion": "={{ $json.ultima_actualizacion }}", "motivo_revision": "={{ $json.motivo_revision }}", "estado_revision": "={{ $json.estado_revision }}", "audios_count": "={{ $json.audios_count }}", "videos_count": "={{ $json.videos_count }}", "fotos_count": "={{ $json.fotos_count }}", "presentacion_ejecucion_url": "={{ $json.presentacion_ejecucion_url }}", "media_folder_url": "={{ $json.media_folder_url }}", "tags": "={{ $json.tags }}", "elementos_detectados": "={{ $json.elementos_detectados }}", "descripcion_ejecucion": "={{ $json.descripcion_ejecucion }}", "resumen_ia": "={{ $json.resumen_ia }}", "comentario_original": "={{ $json.comentario_original }}", "ubicacion": "={{ $json.ubicacion }}", "pais": "={{ $json.pais }}", "cliente": "={{ $json.cliente }}", "marca": "={{ $json.marca }}", "propuesta_link_banco": "={{ $json.propuesta_link_banco }}", "propuesta_nombre_banco": "={{ $json.propuesta_nombre_banco }}", "propuesta_match_confianza": "={{ $json.propuesta_match_confianza }}", "propuesta_match_estado": "={{ $json.propuesta_match_estado }}", "propuesta_referencia": "={{ $json.propuesta_referencia }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "fecha_ejecucion": "={{ $json.fecha_ejecucion }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "ejecucion_id": "={{ $json.ejecucion_id }}" }, "matchingColumns": [], "schema": [ { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_ejecucion", "displayName": "fecha_ejecucion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_referencia", "displayName": "propuesta_referencia", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_match_estado", "displayName": "propuesta_match_estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_match_confianza", "displayName": "propuesta_match_confianza", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_nombre_banco", "displayName": "propuesta_nombre_banco", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "propuesta_link_banco", "displayName": "propuesta_link_banco", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "marca", "displayName": "marca", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "cliente", "displayName": "cliente", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "pais", "displayName": "pais", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ubicacion", "displayName": "ubicacion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comentario_original", "displayName": "comentario_original", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "resumen_ia", "displayName": "resumen_ia", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "descripcion_ejecucion", "displayName": "descripcion_ejecucion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "elementos_detectados", "displayName": "elementos_detectados", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tags", "displayName": "tags", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_folder_url", "displayName": "media_folder_url", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "presentacion_ejecucion_url", "displayName": "presentacion_ejecucion_url", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fotos_count", "displayName": "fotos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audios_count", "displayName": "audios_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado_revision", "displayName": "estado_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actualizacion", "displayName": "ultima_actualizacion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -5152, 2368 ], "id": "1c48ef9f-5d8a-4b7d-89fc-bc8374e5f05d", "name": "Sheets - Guardar propuesta ejecutada", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const filaFinal = $('Code - Preparar fila propuesta ejecutada').first().json;\nconst eventos = filaFinal.eventos_sesion || [];\n\nfunction getRowNumber(row) {\n return (\n row.row_number ||\n row.__row_number ||\n row.__rowNumber ||\n row.rowNumber ||\n row._row_number ||\n ''\n );\n}\n\nreturn eventos\n .map(evento => {\n return {\n json: {\n ...evento,\n row_number: getRowNumber(evento),\n estado: 'PROCESADO',\n ejecucion_id: filaFinal.ejecucion_id,\n fecha_procesado: new Date().toISOString(),\n },\n };\n })\n .filter(item => item.json.row_number);" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -4944, 2368 ], "id": "8b159c83-3b1b-4a0d-b6c6-fcb34fa2ec7b", "name": "Code - Preparar eventos para marcar procesados" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1pXW_Vy__UwFgUY6zjjHEHqjz01nr6Q2eXWpM2YPVfYw/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "estado": "={{ $json.estado }}", "ejecucion_id": "={{ $json.ejecucion_id }}", "fecha_procesado": "={{ $json.fecha_procesado }}" }, "matchingColumns": [ "event_id" ], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -4736, 2368 ], "id": "89a53ce1-73d1-44d2-a229-1a659b2b89b6", "name": "Sheets - Marcar eventos procesados", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const fila = $('Code - Preparar fila propuesta ejecutada').first().json;\n\nconst texto = `Listo. Registré la propuesta ejecutada.\n\nID: ${fila.ejecucion_id}\nMarca/Cliente: ${fila.marca || fila.cliente || 'No disponible'}\nPaís: ${fila.pais || 'No disponible'}\nUbicación: ${fila.ubicacion || 'No disponible'}\n\nGuardé el registro para revisión y procesamiento final.`;\n\nreturn {\n json: {\n ...fila,\n whatsapp_to: String(fila.manager_telefono || '').replace(/\\D/g, ''),\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -4528, 2368 ], "id": "f536693e-a8ff-4cef-bdf3-85622fd2fe30", "name": "Code - Preparar confirmación procesado" }, { "parameters": { "method": "POST", "url": "={{'https://wsp.gomezleemarketing.com'}}/message/sendText/{{'botsoporte'}}", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "={{'C267126ABB45-4C12-B626-6BAB1833F5D7'}}" } ] }, "sendBody": true, "bodyParameters": { "parameters": [ { "name": "number", "value": "={{ String($json.whatsapp_to || '').includes('@') ? String($json.whatsapp_to) : String($json.whatsapp_to || '').replace(/\\D/g, '') + '@s.whatsapp.net' }}" }, { "name": "text", "value": "={{ $json.whatsapp_text }}" }, { "name": "delay", "value": "={{2000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 3632, 320 ], "id": "6c5ba479-a050-47c3-8675-1b21aa8df531", "name": "HTTP Request - Enviar mensaje WhatsApp" }, { "parameters": { "operation": "copy", "fileId": { "__rl": true, "value": "1oDY713ydM5ef9VkfmLPUB3st7qBYPKLU", "mode": "list", "cachedResultName": "TEMPLATE_Propuesta_Ejecutada_Fulgencio.pptx", "cachedResultUrl": "https://docs.google.com/presentation/d/1oDY713ydM5ef9VkfmLPUB3st7qBYPKLU/edit?usp=drivesdk&ouid=110013484451765346305&rtpof=true&sd=true" }, "name": "={{ $('Code - Preparar carpeta ejecución').first().json.presentation_file_name }}", "sameFolder": false, "driveId": { "__rl": true, "mode": "list", "value": "My Drive" }, "folderId": { "__rl": true, "value": "={{ $('Drive - Crear carpeta ejecución').first().json.id }}", "mode": "id" }, "options": {} }, "type": "n8n-nodes-base.googleDrive", "typeVersion": 3, "position": [ -5984, 2368 ], "id": "8144a6cd-6386-4309-86a4-ce290601274d", "name": "Drive - Copiar template presentación", "credentials": { "googleDriveOAuth2Api": { "id": "g23xdGLZRzBGqKgH", "name": "Isaac - Google Drive" } } }, { "parameters": { "jsCode": "const fila = $('Code - Preparar fila propuesta ejecutada').first().json;\nconst slide = $('Drive - Copiar template presentación').first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nconst presentationId = clean(slide.id);\n\nconst presentationUrl =\n clean(slide.webViewLink) ||\n clean(slide.webUrl) ||\n (presentationId ? `https://docs.google.com/presentation/d/${presentationId}/edit` : 'PENDIENTE');\n\nconst replacements = {\n '{{EJECUCION_ID}}': fila.ejecucion_id,\n '{{FECHA_EJECUCION}}': fila.fecha_ejecucion,\n '{{MARCA}}': fila.marca,\n '{{CLIENTE}}': fila.cliente,\n '{{PAIS}}': fila.pais,\n '{{UBICACION}}': fila.ubicacion,\n '{{PROPUESTA_REFERENCIA}}': fila.propuesta_referencia,\n '{{MANAGER_NOMBRE}}': fila.manager_nombre,\n '{{RESUMEN_IA}}': fila.resumen_ia,\n '{{DESCRIPCION_EJECUCION}}': fila.descripcion_ejecucion,\n '{{ELEMENTOS_DETECTADOS}}': fila.elementos_detectados,\n '{{TAGS}}': fila.tags,\n '{{MEDIA_FOLDER_URL}}': fila.media_folder_url,\n '{{FOTOS_COUNT}}': fila.fotos_count,\n '{{VIDEOS_COUNT}}': fila.videos_count,\n '{{AUDIOS_COUNT}}': fila.audios_count,\n};\n\nconst requests = Object.entries(replacements).map(([placeholder, value]) => ({\n replaceAllText: {\n containsText: {\n text: placeholder,\n matchCase: true,\n },\n replaceText: clean(value) || 'No disponible',\n },\n}));\n\nreturn {\n json: {\n ...fila,\n presentation_id: presentationId,\n presentacion_ejecucion_url: presentationUrl,\n slides_requests: requests,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5776, 2368 ], "id": "29840388-f6b6-4ed3-85df-f2f8e8e7cc88", "name": "Code - Preparar reemplazos Slides" }, { "parameters": { "method": "POST", "url": "={{ 'https://slides.googleapis.com/v1/presentations/' + $json.presentation_id + ':batchUpdate' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "sendBody": true, "specifyBody": "json", "jsonBody": "={{\n {\n requests: $json.slides_requests\n }\n}}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -5568, 2368 ], "id": "308e9bfa-2e83-4562-b9d9-2487d923d8eb", "name": "HTTP Request - Reemplazar textos Slides", "credentials": { "googleOAuth2Api": { "id": "eHseMeH39kRcXgOF", "name": "Google account 2" } } }, { "parameters": { "jsCode": "const fila = $('Code - Preparar reemplazos Slides').first().json;\n\nreturn {\n json: {\n ...fila,\n presentacion_ejecucion_url: fila.presentacion_ejecucion_url || 'PENDIENTE',\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -5360, 2368 ], "id": "0f8b0f86-efba-41a9-8f18-dded874bbf48", "name": "Code - Actualizar link presentación" }, { "parameters": { "workflowInputs": { "values": [ { "name": "phone" } ] } }, "type": "n8n-nodes-base.executeWorkflowTrigger", "typeVersion": 1.1, "position": [ -13024, 1680 ], "id": "22670bba-8de0-41fb-a9a0-6da7006f418f", "name": "When Executed by Another Workflow", "disabled": true }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $json.comando }}", "rightValue": "=FORMATO", "operator": { "type": "string", "operation": "equals" }, "id": "c749d60c-b479-42d2-ab4b-32f4ab5ddcb8" } ], "combinator": "and" }, "renameOutput": "={{ true }}" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "c46d57fa-81c0-42e4-a602-6983df1d33b1", "leftValue": "={{ $json.comando }}", "rightValue": "=LISTO", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": "={{ true }}" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "27e1a704-d8e0-442b-a9ed-28430b91429a", "leftValue": "={{ $json.comando }}", "rightValue": "=NORMAL", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": "={{ true }}" } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ -12096, 800 ], "id": "7394a82d-93af-48a3-a710-19f16cb8387c", "name": "ANTERIOR - Switch Comando WhatsApp" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $json.accion_flujo }}", "rightValue": "INICIAR", "operator": { "type": "string", "operation": "equals" }, "id": "d056529b-35e5-4b59-81ea-6390368dcc4a" } ], "combinator": "and" }, "renameOutput": true, "outputKey": "INICIAR" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "8113bb38-04a1-4272-8db8-29cb469d4404", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_AUDIO", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_AUDIO" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "2f985186-3795-4cbc-ac92-e154ade8d7d2", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_IMAGEN", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_IMAGEN" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "2e257327-485f-46c7-b718-b0b2aba3a912", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "FOTOS_LISTAS", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "FOTOS_LISTAS" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "bdfd1a30-d1b1-4072-bfda-168c912317fe", "leftValue": "={{ $json.accion_flujo }}", "rightValue": "MEDIA_VIDEO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "MEDIA_VIDEO " }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "72090cce-6818-43ab-913e-d191b61f50a3", "leftValue": "={{ $json.accion_flujo }} ", "rightValue": "SIN_VIDEO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "SIN_VIDEO" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "6f8333ec-fc61-4c12-bf9e-24d9f21ac1be", "leftValue": "={{ $json.accion_flujo }} ", "rightValue": "LISTO ", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "LISTO " } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ -4688, -912 ], "id": "642adcad-1a3b-44c0-87df-102e00184731", "name": "Switch - Acción flujo guiado" }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n crear_nueva_sesion: false,\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n estado: clean(sesionActiva.estado),\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: Number(sesionActiva.videos_count || 0),\n },\n },\n ];\n}\n\nconst now = new Date().toISOString();\nconst stamp = now.replace(/\\D/g, '').slice(0, 14);\nconst telefono4 = telefono.slice(-4) || '0000';\nconst random = Math.random().toString(36).slice(2, 6).toUpperCase();\n\nconst sessionId = `SES_${stamp}_${telefono4}_${random}`;\n\nreturn [\n {\n json: {\n ...entrada,\n\n crear_nueva_sesion: true,\n\n session_id: sessionId,\n manager_telefono: telefono,\n manager_nombre: clean(entrada.manager_nombre),\n canal_origen: clean(entrada.canal_origen || 'WHATSAPP'),\n\n fecha_inicio: now,\n ultima_actividad: now,\n\n etapa: 'ESPERANDO_AUDIO',\n\n audio_count: 0,\n imagenes_count: 0,\n videos_count: 0,\n\n estado: 'ACTIVA',\n ejecucion_id: '',\n motivo_revision: '',\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1360, -3488 ], "id": "9999fa28-5ba8-47e0-906c-d0fa75c38c30", "name": "Code - Resolver inicio sesión" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1568, -3488 ], "id": "158de422-2b3f-4c03-b98e-f369a22f5944", "name": "Sheets - Leer sesiones existentes", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "b9b21561-7dbb-470f-9bae-22189a2982ad", "leftValue": "={{ $json.crear_nueva_sesion }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1152, -3488 ], "id": "f7cb468c-468a-42a1-bc81-6c7effba59e0", "name": "IF - Crear nueva sesión" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $json.session_id }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "canal_origen": "={{ $json.canal_origen }}", "fecha_inicio": "={{ $json.fecha_inicio }}", "ultima_actividad": "={{ $json.ultima_actividad }}", "etapa": "={{ $json.etapa }}", "audio_count": "={{ $json.audio_count }}", "imagenes_count": "={{ $json.imagenes_count }}", "videos_count": "={{ $json.videos_count }}", "estado": "={{ $json.estado }}", "ejecucion_id": "={{ $json.ejecucion_id }}", "motivo_revision": "={{ $json.motivo_revision }}" }, "matchingColumns": [], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -960, -3520 ], "id": "f700b469-6f13-4219-b1d4-17ef93253e40", "name": "Sheets - Crear sesión reporte", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver inicio sesión').first().json;\n\nconst nombre = String(sesion.manager_nombre || '').trim();\nconst saludo = nombre ? `¡Hola, ${nombre}!` : '¡Hola!';\n\nconst texto = `📸 *Propuestas Ejecutadas - GLM*\n\n${saludo} Bienvenido al registro de propuestas ejecutadas.\n\nEste proceso permite documentar ejecuciones reales para alimentar el banco de evidencias de Fulgencio Fumado.\n\n*Paso 1 de 3 — Nota de voz obligatoria*\n\nEnvía una nota de voz indicando:\n\n• Nombre o referencia de la propuesta ejecutada\n• Marca o cliente\n• País\n• Ubicación de la ejecución\n• Fecha de ejecución\n• Qué se implementó\n• Comentarios o resultados observados\n\nImportante: registra una sola propuesta ejecutada a la vez.`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -784, -3520 ], "id": "7e6f9feb-27d7-48c1-9e0f-ae7991b910ba", "name": "Code - Preparar bienvenida y solicitud audio" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const etapa = String($json.etapa || '').trim();\n\nconst instrucciones = {\n ESPERANDO_AUDIO: 'Actualmente estoy esperando la nota de voz obligatoria.',\n ESPERANDO_IMAGENES: 'Actualmente estoy esperando las imágenes obligatorias de la ejecución.',\n ESPERANDO_VIDEO: 'Actualmente estoy esperando videos opcionales o la confirmación SIN VIDEO.',\n PROCESANDO: 'Tu reporte se encuentra en procesamiento.',\n};\n\nconst detalle =\n instrucciones[etapa] ||\n 'Tienes un reporte activo pendiente de completar.';\n\nconst texto = `⚠️ Ya tienes un reporte de propuesta ejecutada en proceso.\n\n${detalle}\n\nCompleta ese reporte antes de iniciar uno nuevo. Si deseas cancelarlo, escribe: CANCELAR`;\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -784, -3280 ], "id": "1e0e2b10-1771-4396-b11d-2e20a94a90c0", "name": "Code - Preparar aviso sesión activa" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1568, -2896 ], "id": "116153fc-b38b-4f5d-91e4-1e2576748474", "name": "Sheets - Leer sesiones para audio", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n audio_aceptado: false,\n motivo_audio: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_AUDIO') {\n return [\n {\n json: {\n ...entrada,\n audio_aceptado: false,\n motivo_audio: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst audioCountActual = Number(sesionActiva.audio_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n audio_aceptado: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_AUDIO',\n etapa: 'ESPERANDO_AUDIO',\n nueva_etapa: 'ESPERANDO_IMAGENES',\n\n audio_count: audioCountActual + 1,\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1360, -2896 ], "id": "876056a4-7a73-404d-9918-fa2e554ac686", "name": "Code - Resolver sesión para audio" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "dd1bbbb7-a9de-4214-b4a7-7d105803dc3f", "leftValue": "={{ $json.audio_aceptado }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1152, -2896 ], "id": "660d9910-164d-4a9d-b5f1-08f122a2ecaf", "name": "IF - Audio válido para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_audio === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `✅ Ya recibí la nota de voz de tu reporte.\n\nAhora debes enviar al menos una imagen de la ejecución.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ La nota de voz y las imágenes ya fueron recibidas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ Recibí tu nota de voz, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -944, -2800 ], "id": "cac36da7-8a8d-4e8f-a613-c7ad0634fb1b", "name": "Code - Preparar rechazo audio" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "NOTA DE VOZ RECIBIDA", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "fecha_procesado": "=", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -944, -2992 ], "id": "856a2aeb-dce1-46e5-99a7-dea5ac0bfd6a", "name": "Sheets - Guardar evento audio", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para audio').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para audio').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para audio').first().json.nueva_etapa }}", "audio_count": "={{ $('Code - Resolver sesión para audio').first().json.audio_count }}", "estado": "={{ $('Code - Resolver sesión para audio').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -736, -2992 ], "id": "411112c3-733c-45e0-8aa3-898fd9df589c", "name": "Sheets - Actualizar sesión tras audio", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para audio').first().json;\n\nconst texto = `✅ Nota de voz recibida.\n\n*Paso 2 de 3 — Imágenes obligatorias*\n\nAhora envía al menos una foto de la propuesta ejecutada.\n\nPuedes enviar varias imágenes seguidas.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -528, -2992 ], "id": "038cb41c-11e0-46d0-8a16-b43042ca18c8", "name": "Code - Preparar solicitud imágenes" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1680, -2432 ], "id": "843023af-78e4-4998-a71c-36fa15d2eb9e", "name": "Sheets - Leer sesiones para imagen", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionesValidas = rows.filter(row => clean(row.session_id));\n\nconst sesionActiva = sesionesValidas.find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n});\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n imagen_aceptada: false,\n motivo_imagen: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_IMAGENES') {\n return [\n {\n json: {\n ...entrada,\n imagen_aceptada: false,\n motivo_imagen: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst imagenesCountActual = Number(sesionActiva.imagenes_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n imagen_aceptada: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_IMAGENES',\n etapa: 'ESPERANDO_IMAGENES',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: imagenesCountActual + 1,\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1472, -2432 ], "id": "6ade68a0-6bdb-48ca-87bb-7255130e19a9", "name": "Code - Resolver sesión para imagen" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "daee475e-88ff-4d39-9823-17bd9d13435f", "leftValue": "={{ $json.imagen_aceptada }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1264, -2432 ], "id": "30ae3263-566e-4bf5-b34f-8140f246b4ff", "name": "IF - Imagen válida para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_imagen === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Antes de enviar imágenes, debes enviar la nota de voz obligatoria del reporte.\n\nIndica en la nota de voz la propuesta ejecutada, marca o cliente, país, ubicación, fecha y detalles de la ejecución.`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ Las imágenes de tu reporte ya fueron registradas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ Recibí tu imagen, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1056, -2336 ], "id": "8edb8bcb-0ecc-420e-8689-1fe387951c38", "name": "Code - Preparar rechazo imagen" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "IMAGEN RECIBIDA", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -928, -2576 ], "id": "94c6d84e-30d9-43f4-9490-3668f696368e", "name": "Sheets - Guardar evento imagen", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para imagen').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para imagen').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para imagen').first().json.etapa }}", "imagenes_count": "={{ $('Code - Resolver sesión para imagen').first().json.imagenes_count }}", "estado": "={{ $('Code - Resolver sesión para imagen').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -720, -2576 ], "id": "a66f3712-5271-4cf4-804b-fb6a831ebd42", "name": "Sheets - Actualizar sesión tras imagen", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para imagen').first().json;\nconst cantidad = Number(sesion.imagenes_count || 1);\n\nconst texto = `✅ Imagen recibida. Total de imágenes registradas: ${cantidad}.\n\nPuedes enviar más imágenes de esta ejecución.\n\nCuando termines de enviar las imágenes, escribe: FOTOS LISTAS`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -544, -2576 ], "id": "9464c819-ef75-4d59-bc3d-772b2fca0d28", "name": "Code - Preparar confirmación imagen recibida" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1840, -1936 ], "id": "a34138fa-0362-4231-a844-5ab2da4c5c5d", "name": "Sheets - Leer sesiones para fotos listas", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\nconst imagenesCount = Number(sesionActiva.imagenes_count || 0);\n\nif (etapaActual !== 'ESPERANDO_IMAGENES') {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (imagenesCount < 1) {\n return [\n {\n json: {\n ...entrada,\n fotos_listas_valido: false,\n motivo_fotos_listas: 'SIN_IMAGENES',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nreturn [\n {\n json: {\n ...entrada,\n\n fotos_listas_valido: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa: clean(sesionActiva.etapa),\n nueva_etapa: 'ESPERANDO_VIDEO',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: imagenesCount,\n videos_count: Number(sesionActiva.videos_count || 0),\n\n ultima_actividad: now,\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1632, -1936 ], "id": "f5bb8bd9-e4f5-4d2b-b430-4bede17eb178", "name": "Code - Validar fotos listas" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "67809c33-d2b5-4c2a-b551-fac585b1d0a3", "leftValue": "={{ $json.fotos_listas_valido }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1424, -1936 ], "id": "7f6752d1-49c6-41cd-b763-ff7bd4de8771", "name": "IF - Puede pasar a videos" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_fotos_listas === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.motivo_fotos_listas === 'SIN_IMAGENES') {\n texto = `⚠️ Aún no he recibido imágenes para este reporte.\n\nDebes enviar al menos una foto de la propuesta ejecutada antes de escribir FOTOS LISTAS.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Aún falta la nota de voz obligatoria.\n\nEnvía primero la nota de voz con los datos de la propuesta ejecutada.`;\n} else if ($json.etapa === 'ESPERANDO_VIDEO') {\n texto = `✅ Las imágenes ya fueron confirmadas.\n\nAhora puedes enviar videos opcionales y luego escribir LISTO, o escribir SIN VIDEO si no tienes videos.`;\n} else {\n texto = `⚠️ No puedo cerrar la etapa de imágenes en este momento.\n\nCompleta el paso pendiente del reporte antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1072, -1808 ], "id": "ba6a4eac-9317-445f-828b-265d197d08d3", "name": "Code - Preparar rechazo fotos listas" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Validar fotos listas').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Validar fotos listas').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Validar fotos listas').first().json.nueva_etapa }}", "estado": "={{ $('Code - Validar fotos listas').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1120, -2080 ], "id": "7cd59c82-a72d-4ed5-a5fd-cca7c5beb86f", "name": "Sheets - Actualizar sesión a video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Validar fotos listas').first().json;\nconst cantidad = Number(sesion.imagenes_count || 0);\n\nconst texto = `✅ Imágenes recibidas: ${cantidad}.\n\n*Paso 3 de 3 — Videos opcionales*\n\nSi tienes videos de la ejecución, envíalos ahora.\n\nCuando termines de enviar los videos, escribe: LISTO\n\nSi no tienes videos, escribe: SIN VIDEO`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -912, -2080 ], "id": "e00c5ae6-8871-4e3a-a171-3d16cbf7b6b9", "name": "Code - Preparar solicitud videos" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1856, -1504 ], "id": "fbb5a845-ec9e-4f99-a56a-cd238e021a61", "name": "Sheets - Leer sesiones para video", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n video_aceptado: false,\n motivo_video: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\n\nif (etapaActual !== 'ESPERANDO_VIDEO') {\n return [\n {\n json: {\n ...entrada,\n video_aceptado: false,\n motivo_video: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst videosCountActual = Number(sesionActiva.videos_count || 0);\n\nreturn [\n {\n json: {\n ...entrada,\n\n video_aceptado: true,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n etapa_recibida: 'ESPERANDO_VIDEO',\n etapa: 'ESPERANDO_VIDEO',\n\n audio_count: Number(sesionActiva.audio_count || 0),\n imagenes_count: Number(sesionActiva.imagenes_count || 0),\n videos_count: videosCountActual + 1,\n\n ultima_actividad: now,\n\n estado_evento: 'PENDIENTE',\n estado_sesion: 'ACTIVA',\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1648, -1504 ], "id": "f39c9580-7677-47aa-8ea3-ed32eb1db91b", "name": "Code - Resolver sesión para video" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "cae99e4c-7474-4480-a5b3-ab8f1092acfd", "leftValue": "={{ $json.video_aceptado }} ", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1440, -1504 ], "id": "d97ff832-f7ee-4a95-9c75-22f82331fa6c", "name": "IF - Video válido para sesión" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_video === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Antes de enviar videos, debes completar la nota de voz obligatoria del reporte.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `⚠️ Antes de enviar videos, debes enviar al menos una imagen y luego escribir: FOTOS LISTAS`;\n} else {\n texto = `⚠️ Recibí tu video, pero actualmente no corresponde al paso activo de tu reporte.\n\nCompleta el paso pendiente antes de continuar.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1232, -1408 ], "id": "3fc31f53-e0c1-48f7-8963-94126d49f77f", "name": "Code - Preparar rechazo video" }, { "parameters": { "operation": "append", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "columns": { "mappingMode": "defineBelow", "value": { "event_id": "={{ $json.event_id }}", "fecha_recepcion": "={{ $json.fecha_recepcion }}", "manager_telefono": "={{ $json.manager_telefono }}", "manager_nombre": "={{ $json.manager_nombre }}", "message_type": "={{ $json.message_type }}", "texto": "VIDEO RECIBIDO ", "comando": "={{ $json.accion_flujo }}", "tiene_media": "={{ $json.tiene_media }}", "media_count": "={{ $json.media_count }}", "raw_preview": "={{ $json.raw_preview }}", "estado": "={{ $json.estado_evento }}", "session_id": "={{ $json.session_id }}", "canal_origen": "={{ $json.canal_origen }}", "etapa_recibida": "={{ $json.etapa_recibida }}" }, "matchingColumns": [], "schema": [ { "id": "event_id", "displayName": "event_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_recepcion", "displayName": "fecha_recepcion", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "message_type", "displayName": "message_type", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "texto", "displayName": "texto", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "comando", "displayName": "comando", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "tiene_media", "displayName": "tiene_media", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "media_count", "displayName": "media_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "raw_preview", "displayName": "raw_preview", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_procesado", "displayName": "fecha_procesado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa_recibida", "displayName": "etapa_recibida", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1232, -1600 ], "id": "dea462c9-d2d3-44d2-ba01-8bedffbed59e", "name": "Sheets - Guardar evento video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Resolver sesión para video').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Resolver sesión para video').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Resolver sesión para video').first().json.etapa }}", "videos_count": "={{ $('Code - Resolver sesión para video').first().json.videos_count }}", "estado": "={{ $('Code - Resolver sesión para video').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -1024, -1600 ], "id": "3ca59033-d203-4d15-8b45-561b064ec9d8", "name": "Sheets - Actualizar sesión tras video", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const sesion = $('Code - Resolver sesión para video').first().json;\nconst cantidad = Number(sesion.videos_count || 1);\n\nconst texto = `✅ Video recibido. Total de videos registrados: ${cantidad}.\n\nPuedes enviar más videos de esta ejecución.\n\nCuando termines, escribe: LISTO`;\n\nreturn {\n json: {\n ...sesion,\n whatsapp_to: sesion.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -816, -1600 ], "id": "3a24461d-1537-487f-ab15-b56f8d9fb921", "name": "Code - Preparar confirmación video recibido" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -3552, -576 ], "id": "8103d2bc-660e-4b66-8628-e32e5def7369", "name": "Sheets - Leer sesiones para cierre", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const entrada = $('Code - Normalizar evento WhatsApp').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction onlyDigits(value) {\n return clean(value).replace(/\\D/g, '');\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst telefono = onlyDigits(entrada.manager_telefono);\nconst accion = norm(entrada.accion_flujo);\nconst now = new Date().toISOString();\n\nconst sesionActiva = rows\n .filter(row => clean(row.session_id))\n .find(row => {\n return (\n onlyDigits(row.manager_telefono) === telefono &&\n norm(row.estado) === 'ACTIVA'\n );\n });\n\nif (!sesionActiva) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_SESION',\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nconst etapaActual = norm(sesionActiva.etapa);\nconst audioCount = Number(sesionActiva.audio_count || 0);\nconst imagenesCount = Number(sesionActiva.imagenes_count || 0);\nconst videosCount = Number(sesionActiva.videos_count || 0);\n\nif (etapaActual !== 'ESPERANDO_VIDEO') {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'ETAPA_INCORRECTA',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n audio_count: audioCount,\n imagenes_count: imagenesCount,\n videos_count: videosCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (audioCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_AUDIO',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (imagenesCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'SIN_IMAGENES',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nif (accion === 'LISTO' && videosCount < 1) {\n return [\n {\n json: {\n ...entrada,\n cierre_valido: false,\n motivo_cierre: 'LISTO_SIN_VIDEO',\n session_id: clean(sesionActiva.session_id),\n etapa: clean(sesionActiva.etapa),\n imagenes_count: imagenesCount,\n whatsapp_to: telefono,\n },\n },\n ];\n}\n\nreturn [\n {\n json: {\n ...entrada,\n\n cierre_valido: true,\n cierre_tipo: accion,\n\n session_id: clean(sesionActiva.session_id),\n manager_telefono: telefono,\n manager_nombre: clean(sesionActiva.manager_nombre || entrada.manager_nombre),\n canal_origen: clean(sesionActiva.canal_origen || entrada.canal_origen || 'WHATSAPP'),\n\n audio_count: audioCount,\n imagenes_count: imagenesCount,\n videos_count: videosCount,\n\n etapa_anterior: clean(sesionActiva.etapa),\n nueva_etapa: 'PROCESANDO',\n estado_sesion: 'ACTIVA',\n ultima_actividad: now,\n\n whatsapp_to: telefono,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -3264, -576 ], "id": "e70aac97-57e2-4cdd-aec8-4b8f7d78c595", "name": "Code - Validar cierre reporte" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "77d8e579-5dbc-429d-9f5f-5ad6bba8d32e", "leftValue": "={{ $json.cierre_valido }} ", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -3056, -576 ], "id": "a5ec7848-c6c1-40df-9d43-18367fa13d5f", "name": "If" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_cierre === 'SIN_SESION') {\n texto = `⚠️ No tienes un reporte activo de propuestas ejecutadas.\n\nPrimero selecciona la opción de Propuestas ejecutadas en el menú principal para iniciar un reporte.`;\n} else if ($json.motivo_cierre === 'SIN_AUDIO') {\n texto = `⚠️ No puedo procesar el reporte porque falta la nota de voz obligatoria.`;\n} else if ($json.motivo_cierre === 'SIN_IMAGENES') {\n texto = `⚠️ No puedo procesar el reporte porque falta al menos una imagen de la ejecución.`;\n} else if ($json.motivo_cierre === 'LISTO_SIN_VIDEO') {\n texto = `Aún no he recibido videos para este reporte.\n\nSi no tienes videos, escribe: SIN VIDEO\n\nSi tienes videos, envíalos y luego escribe: LISTO`;\n} else if ($json.etapa === 'ESPERANDO_AUDIO') {\n texto = `⚠️ Primero debes enviar la nota de voz obligatoria.`;\n} else if ($json.etapa === 'ESPERANDO_IMAGENES') {\n texto = `⚠️ Primero debes enviar al menos una imagen y luego escribir: FOTOS LISTAS`;\n} else {\n texto = `⚠️ Tu reporte no puede procesarse todavía porque falta completar el paso activo.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2848, -480 ], "id": "41657678-c37f-4b9f-a060-bce5d1b967d9", "name": "Code - Preparar rechazo cierre" }, { "parameters": { "operation": "update", "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 616166581, "mode": "list", "cachedResultName": "wa_ejecuciones_sesiones", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=616166581" }, "columns": { "mappingMode": "defineBelow", "value": { "session_id": "={{ $('Code - Validar cierre reporte').first().json.session_id }}", "ultima_actividad": "={{ $('Code - Validar cierre reporte').first().json.ultima_actividad }}", "etapa": "={{ $('Code - Validar cierre reporte').first().json.nueva_etapa }}", "estado": "={{ $('Code - Validar cierre reporte').first().json.estado_sesion }}" }, "matchingColumns": [ "session_id" ], "schema": [ { "id": "session_id", "displayName": "session_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false }, { "id": "manager_telefono", "displayName": "manager_telefono", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "manager_nombre", "displayName": "manager_nombre", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "canal_origen", "displayName": "canal_origen", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "fecha_inicio", "displayName": "fecha_inicio", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ultima_actividad", "displayName": "ultima_actividad", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "etapa", "displayName": "etapa", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "audio_count", "displayName": "audio_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "imagenes_count", "displayName": "imagenes_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "videos_count", "displayName": "videos_count", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "estado", "displayName": "estado", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "ejecucion_id", "displayName": "ejecucion_id", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "motivo_revision", "displayName": "motivo_revision", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true }, { "id": "row_number", "displayName": "row_number", "required": false, "defaultMatch": false, "display": true, "type": "number", "canBeUsedToMatch": true, "readOnly": true, "removed": true } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -2752, -768 ], "id": "8aad06a9-4e71-4846-a507-01d98cb38036", "name": "Sheets - Actualizar sesión a procesando", "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "const cierre = $('Code - Validar cierre reporte').first().json;\n\nreturn {\n json: {\n session_id: cierre.session_id,\n manager_telefono: cierre.manager_telefono,\n manager_nombre: cierre.manager_nombre,\n canal_origen: cierre.canal_origen,\n\n audio_count: cierre.audio_count,\n imagenes_count: cierre.imagenes_count,\n videos_count: cierre.videos_count,\n\n cierre_tipo: cierre.cierre_tipo,\n estado_procesamiento: 'LISTO_PARA_ANALISIS_IA',\n\n whatsapp_to: cierre.manager_telefono,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2528, -768 ], "id": "c55d3919-462f-4da3-97f8-e1dbfa0d73d2", "name": "Code - Preparar procesamiento final guiado" }, { "parameters": { "documentId": { "__rl": true, "value": "1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk", "mode": "list", "cachedResultName": "Fulgencio - Propuestas Ejecutadas", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 306129743, "mode": "list", "cachedResultName": "wa_ejecuciones_eventos", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1nbeuaW2lxvWJYVFD-E0uJRhTGzUa-nuH2WYItHdTsKk/edit#gid=306129743" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ -2336, -768 ], "id": "5f7d65fd-2ab0-4649-bdad-76c4d07b7921", "name": "Sheets - Leer eventos de sesión final", "alwaysOutputData": true, "credentials": { "googleSheetsOAuth2Api": { "id": "K0hDZh3a85MpOHCs", "name": "Google Sheets account 2" } } }, { "parameters": { "jsCode": "const cierre = $('Code - Preparar procesamiento final guiado').first().json;\nconst rows = $input.all().map(item => item.json || {});\n\nfunction clean(value) {\n return String(value ?? '').trim();\n}\n\nfunction norm(value) {\n return clean(value)\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toUpperCase();\n}\n\nconst sessionId = clean(cierre.session_id);\n\nconst eventosSesion = rows.filter(row => {\n return clean(row.session_id) === sessionId;\n});\n\nconst eventosPendientes = eventosSesion.filter(row => {\n const estado = norm(row.estado);\n return estado === 'PENDIENTE' || estado === '';\n});\n\nconst audios = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'AUDIO';\n});\n\nconst imagenes = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'IMAGE';\n});\n\nconst videos = eventosPendientes.filter(row => {\n return norm(row.message_type) === 'VIDEO';\n});\n\nconst tieneAudio = audios.length >= 1;\nconst tieneImagenes = imagenes.length >= 1;\n\nlet motivoError = '';\n\nif (!tieneAudio) {\n motivoError = 'SIN_AUDIO_REGISTRADO';\n} else if (!tieneImagenes) {\n motivoError = 'SIN_IMAGENES_REGISTRADAS';\n}\n\nconst sesionCompleta = tieneAudio && tieneImagenes;\n\nreturn [\n {\n json: {\n ...cierre,\n\n session_id: sessionId,\n\n sesion_completa_para_analizar: sesionCompleta,\n motivo_error_sesion: motivoError,\n\n total_eventos_sesion: eventosSesion.length,\n total_eventos_pendientes: eventosPendientes.length,\n\n audio_count: audios.length,\n imagenes_count: imagenes.length,\n videos_count: videos.length,\n\n audio_event_id: audios.length ? clean(audios[0].event_id) : '',\n audio_event_ids: audios.map(row => clean(row.event_id)).filter(Boolean),\n imagen_event_ids: imagenes.map(row => clean(row.event_id)).filter(Boolean),\n video_event_ids: videos.map(row => clean(row.event_id)).filter(Boolean),\n\n eventos_audio: audios,\n eventos_imagenes: imagenes,\n eventos_video: videos,\n\n estado_procesamiento: sesionCompleta\n ? 'LISTO_PARA_RECUPERAR_MEDIA'\n : 'CAPTURA_INCOMPLETA',\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -2128, -768 ], "id": "2a57e50d-6db5-45c2-90ec-9e64b6da2ccd", "name": "Code - Consolidar sesión guiada para IA" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "11d390e1-dc34-4160-83f0-5449c93d89a3", "leftValue": "={{ $json.sesion_completa_para_analizar }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ -1920, -768 ], "id": "3e77000f-6a11-4cba-b6ff-4d3f9adee5b5", "name": "IF - Sesión completa para analizar" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "let texto = '';\n\nif ($json.motivo_error_sesion === 'SIN_AUDIO_REGISTRADO') {\n texto = `⚠️ No pude procesar tu reporte porque no encontré la nota de voz obligatoria registrada.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n} else if ($json.motivo_error_sesion === 'SIN_IMAGENES_REGISTRADAS') {\n texto = `⚠️ No pude procesar tu reporte porque no encontré imágenes registradas de la ejecución.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n} else {\n texto = `⚠️ Ocurrió un inconveniente al consolidar las evidencias de tu reporte.\n\nPor favor inicia nuevamente el reporte desde el menú principal.`;\n}\n\nreturn {\n json: {\n ...$json,\n whatsapp_to: $json.manager_telefono,\n whatsapp_text: texto,\n },\n};" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1600, -672 ], "id": "cc847c79-3980-4a7d-a160-487c3ee33360", "name": "Code - Preparar error sesión incompleta" }, { "parameters": { "method": "POST", "url": "https://wsp.gomezleemarketing.com/chat/getBase64FromMediaMessage/botsoporte", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "={{'C267126ABB45-4C12-B626-6BAB1833F5D7'}}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{\n {\n message: {\n key: {\n id: $json.audio_event_id\n }\n },\n convertToMp4: false\n }\n}}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -1600, -960 ], "id": "074efcd5-11af-4e87-8659-cf984c78bdd8", "name": "HTTP Request - Obtener audio Evolution" } ], "connections": { "Code - Normalizar evento WhatsApp": { "main": [ [ { "node": "Respond - OK Evolution", "type": "main", "index": 0 } ] ] }, "Respond - OK Evolution": { "main": [ [ { "node": "IF - Mensaje entrante válido", "type": "main", "index": 0 } ] ] }, "IF - Mensaje entrante válido": { "main": [ [ { "node": "Switch - Acción flujo guiado", "type": "main", "index": 0 } ] ] }, "Code - Preparar formato WhatsApp": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento WhatsApp": { "main": [ [ { "node": "Code - Preparar confirmación recibido", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación recibido": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar respuesta LISTO": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer eventos pendientes": { "main": [ [ { "node": "Code - Consolidar sesión LISTO", "type": "main", "index": 0 } ] ] }, "Code - Consolidar sesión LISTO": { "main": [ [ { "node": "IF - Sesión lista para procesar", "type": "main", "index": 0 } ] ] }, "IF - Sesión lista para procesar": { "main": [ [ { "node": "Code - Preparar carpeta ejecución", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar respuesta LISTO", "type": "main", "index": 0 } ] ] }, "Code - Preparar carpeta ejecución": { "main": [ [ { "node": "Drive - Crear carpeta ejecución", "type": "main", "index": 0 } ] ] }, "Drive - Crear carpeta ejecución": { "main": [ [ { "node": "Code - Preparar análisis IA ejecución", "type": "main", "index": 0 } ] ] }, "Code - Preparar análisis IA ejecución": { "main": [ [ { "node": "Gemini - Analizar texto ejecución", "type": "main", "index": 0 } ] ] }, "Gemini - Analizar texto ejecución": { "main": [ [ { "node": "Code - Preparar fila propuesta ejecutada", "type": "main", "index": 0 } ] ] }, "Code - Preparar fila propuesta ejecutada": { "main": [ [ { "node": "Drive - Copiar template presentación", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar propuesta ejecutada": { "main": [ [ { "node": "Code - Preparar eventos para marcar procesados", "type": "main", "index": 0 } ] ] }, "Code - Preparar eventos para marcar procesados": { "main": [ [ { "node": "Sheets - Marcar eventos procesados", "type": "main", "index": 0 } ] ] }, "Sheets - Marcar eventos procesados": { "main": [ [ { "node": "Code - Preparar confirmación procesado", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación procesado": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Webhook": { "main": [ [ { "node": "Code - Normalizar evento WhatsApp", "type": "main", "index": 0 } ] ] }, "Drive - Copiar template presentación": { "main": [ [ { "node": "Code - Preparar reemplazos Slides", "type": "main", "index": 0 } ] ] }, "Code - Preparar reemplazos Slides": { "main": [ [ { "node": "HTTP Request - Reemplazar textos Slides", "type": "main", "index": 0 } ] ] }, "HTTP Request - Reemplazar textos Slides": { "main": [ [ { "node": "Code - Actualizar link presentación", "type": "main", "index": 0 } ] ] }, "Code - Actualizar link presentación": { "main": [ [ { "node": "Sheets - Guardar propuesta ejecutada", "type": "main", "index": 0 } ] ] }, "When Executed by Another Workflow": { "main": [ [] ] }, "ANTERIOR - Switch Comando WhatsApp": { "main": [ [ { "node": "Code - Preparar formato WhatsApp", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer eventos pendientes", "type": "main", "index": 0 } ], [ { "node": "Sheets - Guardar evento WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Resolver inicio sesión": { "main": [ [ { "node": "IF - Crear nueva sesión", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones existentes": { "main": [ [ { "node": "Code - Resolver inicio sesión", "type": "main", "index": 0 } ] ] }, "IF - Crear nueva sesión": { "main": [ [ { "node": "Sheets - Crear sesión reporte", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar aviso sesión activa", "type": "main", "index": 0 } ] ] }, "Sheets - Crear sesión reporte": { "main": [ [ { "node": "Code - Preparar bienvenida y solicitud audio", "type": "main", "index": 0 } ] ] }, "Code - Preparar bienvenida y solicitud audio": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar aviso sesión activa": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Switch - Acción flujo guiado": { "main": [ [ { "node": "Sheets - Leer sesiones existentes", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para audio", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para imagen", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para fotos listas", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para video", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para cierre", "type": "main", "index": 0 } ], [ { "node": "Sheets - Leer sesiones para cierre", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para audio": { "main": [ [ { "node": "Code - Resolver sesión para audio", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para audio": { "main": [ [ { "node": "IF - Audio válido para sesión", "type": "main", "index": 0 } ] ] }, "IF - Audio válido para sesión": { "main": [ [ { "node": "Sheets - Guardar evento audio", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo audio", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo audio": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento audio": { "main": [ [ { "node": "Sheets - Actualizar sesión tras audio", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras audio": { "main": [ [ { "node": "Code - Preparar solicitud imágenes", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para imagen": { "main": [ [ { "node": "Code - Resolver sesión para imagen", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para imagen": { "main": [ [ { "node": "IF - Imagen válida para sesión", "type": "main", "index": 0 } ] ] }, "IF - Imagen válida para sesión": { "main": [ [ { "node": "Sheets - Guardar evento imagen", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo imagen", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo imagen": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento imagen": { "main": [ [ { "node": "Sheets - Actualizar sesión tras imagen", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras imagen": { "main": [ [ { "node": "Code - Preparar confirmación imagen recibida", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación imagen recibida": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para fotos listas": { "main": [ [ { "node": "Code - Validar fotos listas", "type": "main", "index": 0 } ] ] }, "Code - Validar fotos listas": { "main": [ [ { "node": "IF - Puede pasar a videos", "type": "main", "index": 0 } ] ] }, "IF - Puede pasar a videos": { "main": [ [ { "node": "Sheets - Actualizar sesión a video", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo fotos listas", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo fotos listas": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión a video": { "main": [ [ { "node": "Code - Preparar solicitud videos", "type": "main", "index": 0 } ] ] }, "Code - Preparar solicitud videos": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para video": { "main": [ [ { "node": "Code - Resolver sesión para video", "type": "main", "index": 0 } ] ] }, "Code - Resolver sesión para video": { "main": [ [ { "node": "IF - Video válido para sesión", "type": "main", "index": 0 } ] ] }, "IF - Video válido para sesión": { "main": [ [ { "node": "Sheets - Guardar evento video", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo video", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo video": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Guardar evento video": { "main": [ [ { "node": "Sheets - Actualizar sesión tras video", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión tras video": { "main": [ [ { "node": "Code - Preparar confirmación video recibido", "type": "main", "index": 0 } ] ] }, "Code - Preparar confirmación video recibido": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Code - Preparar solicitud imágenes": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Leer sesiones para cierre": { "main": [ [ { "node": "Code - Validar cierre reporte", "type": "main", "index": 0 } ] ] }, "Code - Validar cierre reporte": { "main": [ [ { "node": "If", "type": "main", "index": 0 } ] ] }, "If": { "main": [ [ { "node": "Sheets - Actualizar sesión a procesando", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar rechazo cierre", "type": "main", "index": 0 } ] ] }, "Code - Preparar rechazo cierre": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] }, "Sheets - Actualizar sesión a procesando": { "main": [ [ { "node": "Code - Preparar procesamiento final guiado", "type": "main", "index": 0 } ] ] }, "Code - Preparar procesamiento final guiado": { "main": [ [ { "node": "Sheets - Leer eventos de sesión final", "type": "main", "index": 0 } ] ] }, "Sheets - Leer eventos de sesión final": { "main": [ [ { "node": "Code - Consolidar sesión guiada para IA", "type": "main", "index": 0 } ] ] }, "Code - Consolidar sesión guiada para IA": { "main": [ [ { "node": "IF - Sesión completa para analizar", "type": "main", "index": 0 } ] ] }, "IF - Sesión completa para analizar": { "main": [ [ { "node": "HTTP Request - Obtener audio Evolution", "type": "main", "index": 0 } ], [ { "node": "Code - Preparar error sesión incompleta", "type": "main", "index": 0 } ] ] }, "Code - Preparar error sesión incompleta": { "main": [ [ { "node": "HTTP Request - Enviar mensaje WhatsApp", "type": "main", "index": 0 } ] ] } }, "authors": "Isaac Aracena", "name": "Version 9593f621", "description": "", "autosaved": true, "workflowPublishHistory": [ { "createdAt": "2026-06-04T00:42:28.663Z", "id": 1076, "workflowId": "t6lFUulNtDIR3tAm", "versionId": "9593f621-8097-459c-8c53-d734fafaffe2", "event": "activated", "userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" }, { "createdAt": "2026-06-04T00:42:34.047Z", "id": 1078, "workflowId": "t6lFUulNtDIR3tAm", "versionId": "9593f621-8097-459c-8c53-d734fafaffe2", "event": "activated", "userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" }, { "createdAt": "2026-06-04T00:42:33.977Z", "id": 1077, "workflowId": "t6lFUulNtDIR3tAm", "versionId": "9593f621-8097-459c-8c53-d734fafaffe2", "event": "deactivated", "userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" } ] } }