{ "$json": { "updatedAt": "2026-08-27T17:54:08.335Z", "createdAt": "2026-06-08T13:50:12.174Z", "id": "F1iPg8hktNAebZua", "name": "GLMWay", "description": null, "active": true, "isArchived": false, "nodes": [ { "parameters": { "httpMethod": "POST", "path": "glmway", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -352, -144 ], "id": "4cff954f-86fd-4835-8463-b083e3a66f35", "name": "Webhook", "webhookId": "2dea176c-88de-41b6-851d-c9f6a703ab69" }, { "parameters": {}, "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ 3104, 768 ], "id": "a2082638-94e3-4a91-aeac-f7849833a6a1", "name": "When clicking ‘Execute workflow’" }, { "parameters": { "method": "POST", "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $('Valores').item.json.user }}/{{ $('Valores').item.json.repo_name }}/contents/{{ $('Valores').item.json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"message\": \"{{ $json.message }}\",\n \"content\": \"{{ $json.content }}\",\n \"branch\": \"{{ $json.branch }}\"\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 4080, 880 ], "id": "e428eaaf-f678-45ac-bbcc-926f8bd574b7", "name": "Subir archivo", "retryOnFail": false, "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } } }, { "parameters": { "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $json.user }}/{{ $json.repo_name }}/contents/{{ $json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendHeaders": true, "headerParameters": { "parameters": [] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3472, 768 ], "id": "58d2c064-8982-42b0-8f1a-a10d018dff94", "name": "Obtener archivo", "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } }, "onError": "continueErrorOutput" }, { "parameters": { "method": "PUT", "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $('Valores').item.json.user }}/{{ $('Valores').item.json.repo_name }}/contents/{{ $('Valores').item.json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"message\": \"{{ $json.message }}\",\n \"content\": \"{{ $json.content }}\",\n \"sha\": \"{{ $json.sha }}\",\n \"branch\": \"{{ $json.branch }}\"\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 4080, 672 ], "id": "f804d797-946f-4673-8291-308d47ede436", "name": "Actualizar archivo", "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } } }, { "parameters": { "operation": "get", "workflowId": { "__rl": true, "value": "F1iPg8hktNAebZua", "mode": "list", "cachedResultName": "GLMWay (#F1iPg8hktNAebZua)" }, "requestOptions": {} }, "type": "n8n-nodes-base.n8n", "typeVersion": 1, "position": [ 3728, 672 ], "id": "a6420476-f217-4079-b7a0-194969a2dac2", "name": "Get a workflow1", "credentials": { "n8nApi": { "id": "73Ydc9X8h5HXvFrt", "name": "Eidan - n8n account" } } }, { "parameters": { "operation": "get", "workflowId": { "__rl": true, "value": "F1iPg8hktNAebZua", "mode": "list", "cachedResultName": "GLMWay (#F1iPg8hktNAebZua)" }, "requestOptions": {} }, "type": "n8n-nodes-base.n8n", "typeVersion": 1, "position": [ 3728, 880 ], "id": "f96e2477-f9db-4d36-a162-836d05dcd8ab", "name": "Get a workflow2", "credentials": { "n8nApi": { "id": "73Ydc9X8h5HXvFrt", "name": "Eidan - n8n account" } } }, { "parameters": { "assignments": { "assignments": [ { "id": "31558805-f167-47c4-b0b4-46b8a80ca282", "name": "user", "value": "mgomez", "type": "string" }, { "id": "3519ad4c-6d66-4963-ab76-ee5517d88d67", "name": "repo_name", "value": "calendario-glm-way", "type": "string" }, { "id": "0df99f1e-1354-43b9-9d20-9f994cc82cf6", "name": "file_name", "value": "glmway-workflow", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 3296, 768 ], "id": "fa4f3a95-6fe7-41c4-9a90-f4a3f58e06a8", "name": "Valores" }, { "parameters": { "jsCode": "const sha = $('Obtener archivo').first().json.sha;\nconst data = { $json };\n\nreturn [{\n json: {\n message: \"Update \" + $('Valores').first().json.file_name + \".json\",\n content: Buffer.from(JSON.stringify(data, null, 2)).toString(\"base64\"),\n sha: sha,\n branch: \"main\"\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3904, 672 ], "id": "5d50d650-f0b6-4046-b9c1-974664b655f6", "name": "Code in JavaScript2" }, { "parameters": { "jsCode": "const sha = $json.sha; // viene del GET anterior\nconst data = { $json };\n\nconst base64 = Buffer.from(JSON.stringify(data, null, 2)).toString(\"base64\");\n\nreturn [{\n json: {\n message: \"Create \" + $('Valores').first().json.file_name + \".json\",\n content: base64,\n sha: sha,\n branch: \"main\"\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3904, 880 ], "id": "30ffb25f-3ad7-465d-9630-887828df95f6", "name": "Code in JavaScript4" }, { "parameters": { "operation": "get", "employeeId": "={{ $json.body.employees[0].id }}", "options": {} }, "type": "n8n-nodes-base.bambooHr", "typeVersion": 1, "position": [ -176, -144 ], "id": "5b4b3106-f932-4430-a11e-ebcc1740f884", "name": "Get an employee", "credentials": { "bambooHrApi": { "id": "VwYITXROyinOC4je", "name": "Eidan - BambooHR account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 16 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -336, 2144 ], "id": "7f7d71b2-6c53-49a2-92d8-e66b2d0bff54", "name": "Schedule Trigger" }, { "parameters": { "url": "=https://glm.bamboohr.com/api/v1/employees/{{ $json.id }}?fields=supervisorEmail,hireDate,supervisorEId,jobTitle", "authentication": "genericCredentialType", "genericAuthType": "httpBasicAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "application/json" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 0, -144 ], "id": "ae2aff4d-5874-4181-9801-cf51d5cc4ff3", "name": "Informacion extra del empleado", "retryOnFail": true, "waitBetweenTries": 2000, "credentials": { "httpBasicAuth": { "id": "vXrW3oJWVhNbzB07", "name": "GLM Credential" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ Object.keys($json).length }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 912, -352 ], "id": "8a2be7cc-85ad-4e44-92a7-fe3f94df703f", "name": "Hay coordinador?" }, { "parameters": { "content": "## Formato fecha\nyyyy-mm-dd\n", "height": 192, "width": 192 }, "type": "n8n-nodes-base.stickyNote", "position": [ 128, -224 ], "typeVersion": 1, "id": "8de8b400-70cb-4367-bddc-d42876f18d52", "name": "Sticky Note" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $json.isValid }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 528, -256 ], "id": "cb43a2bb-7743-4994-a7b2-209cd0934cd7", "name": "Entra hoy?" }, { "parameters": { "rule": { "interval": [ { "field": "hours" } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 352 ], "id": "20e1c800-bf0b-4484-b836-14bc7154e4e7", "name": "Schedule Trigger1" }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Get an employee').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ null }}" }, { "fieldId": "estado", "fieldValue": "inactivo" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 752, -80 ], "id": "0a800bb8-d5f1-443e-b3b1-3ca9546eb28f", "name": "Insertar a inscritos (inactivo)", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "const hireDate = $json.hireDate;\n\n// Fecha de hoy en formato YYYY-MM-DD\nconst today = new Date().toISOString().split('T')[0];\n\n// True si hireDate es hoy o anterior\nconst isValid = hireDate <= today;\n\nreturn [\n {\n json: {\n hireDate,\n today,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 176, -144 ], "id": "241cf92b-09b1-4555-af46-7b9ff49c5e37", "name": "Calcular fecha hireDate" }, { "parameters": { "content": "## Numero wsp Matos\n\n18494105855@s.whatsapp.net", "height": 192, "width": 192 }, "type": "n8n-nodes-base.stickyNote", "position": [ 784, -640 ], "typeVersion": 1, "id": "719365c8-8099-4108-a910-83b651d81181", "name": "Sticky Note1" }, { "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": "={{ \"18494105855@s.whatsapp.net\" }}" }, { "name": "mediatype", "value": "=image" }, { "name": "text", "value": "=⚠️ No hay coordinador RRHH en el país de este nuevo ingreso:\n\nNombre: {{ $('Get an employee').item.json.displayName }}\nCorreo: {{ $('Get an employee').item.json.workEmail }}\nPaís: {{ $('Get an employee').item.json.location }}\n\n#GLMWay" }, { "name": "delay", "value": "={{5000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1088, -192 ], "id": "09ce1f03-3dfb-4108-9d25-6c05ac622a6f", "name": "Alerta no hay coordinador RRHH" }, { "parameters": { "operation": "get", "employeeId": "={{ $json.empleado_id }}", "options": {} }, "type": "n8n-nodes-base.bambooHr", "typeVersion": 1, "position": [ 192, 352 ], "id": "9e00d1ce-5533-4357-977e-31a8da97f232", "name": "Get an employee1", "retryOnFail": true, "credentials": { "bambooHrApi": { "id": "VwYITXROyinOC4je", "name": "Eidan - BambooHR account" } } }, { "parameters": { "url": "=https://glm.bamboohr.com/api/v1/employees/{{ $json.id }}?fields=supervisorEmail,hireDate,supervisorEId,jobTitle", "authentication": "genericCredentialType", "genericAuthType": "httpBasicAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "application/json" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 352 ], "id": "06c32cb0-a8ab-42c1-ae36-fe628b1b5e2b", "name": "Informacion extra del empleado1", "retryOnFail": true, "waitBetweenTries": 2000, "credentials": { "httpBasicAuth": { "id": "vXrW3oJWVhNbzB07", "name": "GLM Credential" } } }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -16, 352 ], "id": "36c1682f-35a1-4016-b2ac-77f7e20e3e59", "name": "Loop Over Items" }, { "parameters": { "sendTo": "={{ $('Get an employee').item.json.workEmail }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=Hola, GLMer!\n\nEste {{ $('Convertir fecha a espanol').item.json.fechaFormateada }} a las {{ $json.hora_convertida }} tenemos entrenamiento, y queremos transmitirte nuestra cultura, nuestro ADN y por qué somos diferentes al resto.\n\nTe esperamos puntual y con todas las ganas de aprender.\n\nNos vemos en el enlace!\n\n{{ $('Obtener sesiones español').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2656, -336 ], "id": "e6c3acf5-d54b-4e00-b7a9-74038d27e387", "name": "Send a message espanol", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Get an employee').item.json.workEmail }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis {{ $('Convertir fecha a ingles').item.json.fechaFormateada }} at {{ $json.hora_convertida }} we have training, and we want to share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesiones ingles').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2656, -160 ], "id": "f173c8d1-9311-405c-a7ee-164726df32f1", "name": "Send a message ingles", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "content": "## Recordatorio a nuevo ingreso 24 horas antes de la sesion\n", "height": 480, "width": 2256, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 736 ], "typeVersion": 1, "id": "ba58d863-3211-4f53-b087-eb53ba839499", "name": "Sticky Note2" }, { "parameters": { "content": "## Recordatorio a coordinador RRHH 48 y 24 horas antes de la sesion\n", "height": 496, "width": 2928, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 1280 ], "typeVersion": 1, "id": "e32bdd94-d61e-4b43-bf60-7acab8c0d3ae", "name": "Sticky Note3" }, { "parameters": { "content": "## Envio de formulario de evaluacion despues que la sesion finalize", "height": 304, "width": 2976, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 2656 ], "typeVersion": 1, "id": "6d5c0fe5-5ab1-4cdc-bfd2-197dc2144274", "name": "Sticky Note4" }, { "parameters": { "content": "## Notificacion inicial\n\nEnvia notificacion de sesion en el primer dia de trabajo del empleado", "height": 608, "width": 3424, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, -480 ], "typeVersion": 1, "id": "cd2fe5c5-9963-410b-a61a-edc36b5aaed1", "name": "Sticky Note5" }, { "parameters": { "content": "## Completar datos y enviar invitacion", "height": 544, "width": 4032, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 160 ], "typeVersion": 1, "id": "126bdd3f-a050-4053-aff3-e625c8bf161c", "name": "Sticky Note6" }, { "parameters": { "jsCode": "const hireDate = $json.hireDate;\n\n// Fecha de hoy en formato YYYY-MM-DD\nconst today = new Date().toISOString().split('T')[0];\n\n// True si hireDate es hoy o anterior\nconst isValid = hireDate <= today;\n\nreturn [\n {\n json: {\n hireDate,\n today,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 560, 352 ], "id": "26d7adef-3c91-410e-b92f-69841d28c039", "name": "Calcular fecha hireDate1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $json.isValid }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 944, 352 ], "id": "15a1892d-01e8-432c-91f1-db236317cbca", "name": "Entra hoy?1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ [\"Jamaica\", \"Trinidad and Tobago\", \"Barbados\", \"Saint Thomas\", \"St. Croix\", \"Tobago\", \"Guyana\", \"Aruba\"].includes($('Get an employee1').item.json.location) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "false", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1696, 352 ], "id": "ce9f31d4-454e-4e31-9a22-8173b3fae392", "name": "Pais?1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ Object.keys($json).length }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 1328, 256 ], "id": "30b3a4dd-6d50-405d-9c77-27febcc50aa4", "name": "Hay coordinador?1" }, { "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": "={{ \"18494105855@s.whatsapp.net\" }}" }, { "name": "mediatype", "value": "=image" }, { "name": "text", "value": "=⚠️ No hay coordinador RRHH en el país de este nuevo ingreso:\n\nNombre: {{ $('Get an employee1').item.json.displayName }}\nCorreo: {{ $('Get an employee1').item.json.workEmail }}\nPaís: {{ $('Get an employee1').item.json.location }}\n\n#GLMWay" }, { "name": "delay", "value": "={{5000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1504, 384 ], "id": "67928478-7604-45a4-9ab0-851079e1470c", "name": "Alerta no hay coordinador RRHH1" }, { "parameters": { "sendTo": "={{ $('Get an employee1').item.json.workEmail }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=Hola, GLMer!\n\nEste {{ $('Convertir fecha a espanol1').item.json.fechaFormateada }} a las {{ $json.hora_convertida }} tenemos entrenamiento, y queremos transmitirte nuestra cultura, nuestro ADN y por qué somos diferentes al resto.\n\nTe esperamos puntual y con todas las ganas de aprender.\n\nNos vemos en el enlace!\n\n{{ $('Obtener sesiones español1').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 3072, 272 ], "id": "32302b24-aa4c-4f9a-afc8-ef7e86cad56b", "name": "Send a message espanol1", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Get an employee1').item.json.workEmail }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis {{ $('Convertir fecha a ingles1').item.json.fechaFormateada }} at {{ $json.hora_convertida }} we have training, and we want to share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesiones ingles1').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 3072, 448 ], "id": "db2cb6a3-1da8-472a-95eb-1a02de2a5fa4", "name": "Send a message ingles1", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ [\"Jamaica\", \"Trinidad and Tobago\", \"Barbados\", \"Saint Thomas\", \"St. Croix\", \"Tobago\", \"Guyana\", \"Aruba\"].includes($('Get an employee').item.json.location) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "false", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1328, -256 ], "id": "b183c892-8822-4bc3-a92c-4410eac41a01", "name": "Pais?" }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 3488, 352 ], "id": "98185de1-e81a-440f-8951-f98bd78c707b", "name": "Wait", "webhookId": "22a77d35-7adb-47ec-beca-0fae7615ab5b" }, { "parameters": { "content": "## Notificacion a facilitador\n\n- Manda un listado de las personas inscritas en la sesion del miercoles al facilitador.\n- Si no hay personas inscritas envia un alerta al facilitador.", "height": 768, "width": 2208, "color": 3 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 1824 ], "typeVersion": 1, "id": "79ccf49e-4434-4b72-8147-ad27b9d994a2", "name": "Sticky Note8" }, { "parameters": { "sendTo": "={{ $('Loop Over Items1').item.json.email }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=¡Hola, GLMer!\n\nTe recordamos que la sesión de capacitación será el {{ $('Convertir fecha a espanol2').item.json.fechaFormateada }} a las {{ $json.hora_convertida }}. Queremos compartir nuestra cultura, nuestro ADN y aquello que nos hace diferentes al resto.\n\nContamos con tu puntualidad y tus ganas de aprender.\n\n¡Nos vemos en el enlace!\n\n{{ $('Obtener sesion').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1344, 752 ], "id": "10b2cb4e-274d-4913-9345-2c024c071f4c", "name": "Send a message espanol2", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Loop Over Items1').item.json.email }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis is a reminder about your training session on {{ $('Convertir fecha a ingles2').item.json.fechaFormateada }} at {{ $json.hora_convertida }} where we’ll share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesion').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1344, 960 ], "id": "1dc76989-8c58-4ffe-9e1c-5113a59d346c", "name": "Send a message ingles2", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 2, 3 ], "triggerAtHour": 17 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 928 ], "id": "60708d5c-0cd7-45fc-bb67-ed050c1f8022", "name": "Schedule Trigger2" }, { "parameters": { "operation": "get", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "estado", "keyValue": "inactivo" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 352 ], "id": "93a65a61-59a9-4903-8a35-dbf66a0ef468", "name": "Obtener inactivos", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ 0, 928 ], "id": "9e8fd238-541e-455b-8ae5-6a3097eb38a0", "name": "Loop Over Items1" }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 1728, 1088 ], "id": "ee5bb9bc-b8cb-493f-8463-ae0a24cf1f0d", "name": "Wait1", "webhookId": "09d53dc8-c92a-43d2-a47f-477c0d1317af" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ !['Jamaica', 'Trinidad and Tobago', 'Barbados', 'Saint Thomas', 'St. Croix', 'Tobago', 'Guyana', 'Aruba'].includes($('Obtener notificados').item.json.pais) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 752, 832 ], "id": "4d94c907-8ab1-4213-be20-9e24173cf0a3", "name": "Pais?2" }, { "parameters": { "assignments": { "assignments": [ { "id": "1e6f83ce-19e7-4dd9-ba34-a11836a6181e", "name": "idioma", "value": "ES", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1552, -336 ], "id": "e8a65f36-8e8e-4135-b7a2-a7ef4617de2f", "name": "Crear variable idioma ES" }, { "parameters": { "assignments": { "assignments": [ { "id": "b0610214-1357-4e55-be5f-75c159d3b717", "name": "idioma", "value": "EN", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1552, -160 ], "id": "971ae719-5692-4f87-9a57-2287ee44783d", "name": "Crear variable idioma EN" }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1744, -336 ], "id": "cb9e8a10-a1e7-40c7-8447-2379b0191a8f", "name": "Obtener sesiones español", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1744, -160 ], "id": "5ca790ee-4944-4868-98af-89837ac39422", "name": "Obtener sesiones ingles", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1936, -336 ], "id": "c2db5e62-7741-4ff2-ad31-71c108dd7386", "name": "Calcular sesion mas cercana" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1936, -160 ], "id": "bde8fba9-0d6c-4299-8971-dcd8e0e740b4", "name": "Calcular sesion mas cercana1" }, { "parameters": { "assignments": { "assignments": [ { "id": "1e6f83ce-19e7-4dd9-ba34-a11836a6181e", "name": "idioma", "value": "ES", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1952, 272 ], "id": "430a2b66-f0f3-4032-bca1-29b01bd8c577", "name": "Crear variable idioma ES1" }, { "parameters": { "assignments": { "assignments": [ { "id": "b0610214-1357-4e55-be5f-75c159d3b717", "name": "idioma", "value": "EN", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1952, 448 ], "id": "9d53a7e1-6dab-494b-8064-6c3063f5596f", "name": "Crear variable idioma EN1" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?1').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2336, 272 ], "id": "ee31fd24-d703-44b3-b65b-75234564d29f", "name": "Calcular sesion mas cercana2" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?1').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2336, 448 ], "id": "24f2e53d-9280-445b-b37e-776b41ca53e2", "name": "Calcular sesion mas cercana3" }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" }, { "fieldId": "coordinador_rrhh", "fieldValue": "={{ $('Obtener coordinador3').item.json.nombre }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2096, -336 ], "id": "dcdef9fc-9c61-45dd-9604-56037eac4c31", "name": "Guardar datos del empleado y sesion asignada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" }, { "fieldId": "coordinador_rrhh", "fieldValue": "={{ $('Obtener coordinador3').item.json.nombre }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2096, -160 ], "id": "7530270a-b32e-419e-8fc5-b29fa07dda39", "name": "Guardar datos del empleado y sesion asignada1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2144, 272 ], "id": "f034ee45-742b-4f18-9003-333a4c087cf7", "name": "Obtener sesiones español1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2144, 448 ], "id": "2c35fe0e-1f32-4263-9c02-c392cb77e0e5", "name": "Obtener sesiones ingles1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 1136, 496 ], "id": "960e74ae-583b-4802-ab72-3b402c095d9b", "name": "Wait2", "webhookId": "1211d7da-55b9-4a73-837d-55934076a799" }, { "parameters": { "operation": "get", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "estado", "keyValue": "notificado" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 928 ], "id": "34aa0bc5-0feb-46e3-871b-27a1cc418675", "name": "Obtener notificados", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.isValid }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 416, 928 ], "id": "107b41cb-06d5-4e7e-863b-dace19c8d1e9", "name": "Falta 24h para el evento?" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Loop Over Items1').item.json.empleado_id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "estado", "fieldValue": "recordado" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1568, 880 ], "id": "ddf0a273-d3bc-44cc-888b-d789ce72ff77", "name": "Actualizar estado a recordado", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 2 ], "triggerAtHour": 16 }, { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 16 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 1504 ], "id": "6951af7d-5098-4156-81bd-8f67034fcf70", "name": "Schedule Trigger3" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.pais }}", "rightValue": "Jamaica", "operator": { "type": "string", "operation": "equals" } }, { "id": "32931394-f4ea-4055-b866-906a81988173", "leftValue": "={{ $json.pais }}", "rightValue": "Trinidad and Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "ea2a8466-96c6-460f-b08f-d23c06b2d18c", "leftValue": "={{ $json.pais }}", "rightValue": "Barbados", "operator": { "type": "string", "operation": "equals" } }, { "id": "28e49217-0c1a-4462-9642-676e54926d3e", "leftValue": "={{ $json.pais }}", "rightValue": "Saint Thomas", "operator": { "type": "string", "operation": "equals" } }, { "id": "c6a6aea5-48f4-44dc-92ca-a9f9de9cacf9", "leftValue": "={{ $json.pais }}", "rightValue": "St. Croix", "operator": { "type": "string", "operation": "equals" } }, { "id": "e6f52339-ea7c-462f-bdc2-8b7353160e4c", "leftValue": "={{ $json.pais }}", "rightValue": "Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "b308c2b6-53b4-4d49-b540-cdc03e36528b", "leftValue": "={{ $json.pais }}", "rightValue": "Guyana", "operator": { "type": "string", "operation": "equals" } }, { "id": "35a50a33-a2b5-4116-9336-11300357569e", "leftValue": "={{ $json.pais }}", "rightValue": "Aruba", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1520, 1488 ], "id": "13ee807a-f1cd-48ef-921b-7b5c260ba116", "name": "Pais?3" }, { "parameters": { "jsCode": "// Helper para parsear \"14 December\" → Date (año actual)\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\n// Formatear fecha como \"26 June\"\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\nconst fecha_sesion = $input.first().json.fecha_sesion_inscrito;\n\n// Fecha de hoy normalizada a medianoche\nconst hoy = new Date();\nhoy.setHours(0, 0, 0, 0);\n\nconst sesion = parseSessionDate(fecha_sesion);\nsesion.setHours(0, 0, 0, 0);\n\n// Diferencia en días\nconst diferenciaDias = Math.floor(\n (sesion - hoy) / (1000 * 60 * 60 * 24)\n);\n\n// True si es hoy (0 días) o mañana (1 día)\nconst isValid = diferenciaDias >= 0 && diferenciaDias <= 1;\n\nreturn [\n {\n json: {\n fecha_sesion,\n fecha_hoy: formatDate(hoy),\n diferenciaDias,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 208, 928 ], "id": "bbd0558c-3b3a-462b-957c-83b1975e5413", "name": "Calcular falta 24h o es el mismo dia" }, { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "expression": "0 0 0 1 1 *" } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 3440, -352 ], "id": "ca136518-b776-45ba-b1a2-ad5327dd4cca", "name": "Schedule Trigger4" }, { "parameters": { "operation": "appendOrUpdate", "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "Fecha": "={{ $json.start }}" }, "matchingColumns": [ "Fecha" ], "schema": [ { "id": "Fecha", "displayName": "Fecha", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 4336, -352 ], "id": "7c321f7d-bce9-447c-b94c-35f6967a48e3", "name": "Insertar fechas", "alwaysOutputData": false, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": {}, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 4160, -352 ], "id": "27531838-5dc7-4169-a08a-f4da93899580", "name": "Wait4", "webhookId": "85cfdcd9-384b-47e8-9d7d-4e079f0a4d97" }, { "parameters": { "operation": "clear", "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "clear": "specificRange", "range": "A2:D80" }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 3984, -352 ], "id": "bd8cb535-6aa3-46df-9ca0-6efc0555f2e4", "name": "Borrar fechas", "alwaysOutputData": false, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "content": "## Borrar y guardar las nuevas fechas de las sesiones del nuevo año en el sheets\n\nEste trigger se activa todos los años el 1 de enero", "height": 288, "width": 1072 }, "type": "n8n-nodes-base.stickyNote", "position": [ 3408, -480 ], "typeVersion": 1, "id": "ddcb9db1-2590-4364-aeeb-db79c35ea604", "name": "Sticky Note10" }, { "parameters": { "sendTo": "={{ $json.email }}", "subject": "Evaluación #TheGLMWay", "message": "=\n\n\n \n \n Gracias por tu participación #TheGLMWay\n\n\n
\n\n\n \n \n \n \n
\n

Evaluación #TheGLMWay

\n
\n \"GLM\n
\n \n
\n

\n Hola {{ $json.primerNombre }},\n

\n

\n ¡Gracias por participar en la sesión #TheGLMWay!

\n

\n Para seguir mejorando estos espacios, nos encantaría conocer tu opinión sobre lo visto en la sesión. Responder la evaluación te tomará menos de 5 minutos.\n

\n \n
\n
\n \"Google\n

Evaluación #TheGLMWay

\n
\n \n \n Completar evaluación\n \n
\n
\n
\n\n", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2400, 2848 ], "id": "3c22bc65-799f-4432-86fe-10ae92e036de", "name": "Send a message espanol4", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $json.email }}", "subject": "#TheGLMWay Quiz", "message": "=\n\n\n \n \n Thank you for participating #TheGLMWay\n\n\n
\n\n\n \n \n \n \n
\n

#TheGLMWay Quiz

\n
\n \"GLM\n
\n \n
\n

\n Hi {{ $json.primerNombre }},\n

\n

\n Thank you for taking part in the #TheGLMWay session!

\n

\n To keep improving these sessions, we'd love to hear your thoughts on what was covered. Completing the quiz will take less than 5 minutes.\n

\n \n
\n
\n \"Google\n

#TheGLMWay Quiz

\n
\n \n \n Complete quiz\n \n
\n
\n
\n\n", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2400, 2672 ], "id": "4dfc0135-6886-4d33-9b2a-a26efbe72832", "name": "Send a message ingles4", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "operation": "getAll", "calendar": { "__rl": true, "value": "ethen@gomezleemarketing.com", "mode": "list", "cachedResultName": "ethen@gomezleemarketing.com" }, "returnAll": true, "timeMin": "={{ $now.startOf('year') }}", "timeMax": "={{ $now.endOf('year') }}", "options": { "orderBy": "startTime", "query": "#TheGLMWay" } }, "type": "n8n-nodes-base.googleCalendar", "typeVersion": 1.3, "position": [ 3632, -352 ], "id": "b2b03ce6-6010-4e4f-be7a-d9040286e295", "name": "Obtener entrenamientos ingles y espanol", "credentials": { "googleCalendarOAuth2Api": { "id": "yEmGG4av5RxOK7wu", "name": "Eidan - Google Calendar account" } } }, { "parameters": { "jsCode": "const months = [\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];\n\nfunction formatDate(dateTimeStr) {\n if (!dateTimeStr) return null;\n const datePart = dateTimeStr.split('T')[0]; // \"2026-01-07\"\n const [year, month, day] = datePart.split('-');\n return `${parseInt(day, 10)} ${months[parseInt(month, 10) - 1]}`;\n}\n\nconst output = [];\n\nfor (const item of $input.all()) {\n const event = item.json;\n output.push({\n json: {\n id: event.id,\n summary: event.summary,\n start: `'${formatDate(event.start?.dateTime || event.start?.date)}`,\n end: formatDate(event.end?.dateTime || event.end?.date)\n }\n });\n}\n\nreturn output;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3808, -352 ], "id": "73c39af9-bc01-4d97-81ee-846aff70b3a6", "name": "Formatear fecha" }, { "parameters": { "rule": { "interval": [ { "triggerAtHour": 11 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 3440, -48 ], "id": "55a755d8-8b74-440f-93c6-8a1ecba4c666", "name": "Schedule Trigger5" }, { "parameters": { "content": "## Añadir/actualizar coordinadores RRHH\nEste trigger se activa todos los dias a las 11am", "height": 288, "width": 1072 }, "type": "n8n-nodes-base.stickyNote", "position": [ 3408, -160 ], "typeVersion": 1, "id": "3fd1379f-78d1-40a8-b24f-f8f086fda80a", "name": "Sticky Note12" }, { "parameters": { "operation": "getAll", "calendar": { "__rl": true, "value": "ethen@gomezleemarketing.com", "mode": "list", "cachedResultName": "ethen@gomezleemarketing.com" }, "returnAll": true, "timeMin": "={{ $now.startOf('year') }}", "timeMax": "={{ $now.endOf('year') }}", "options": { "orderBy": "startTime", "query": "#TheGLMWay" } }, "type": "n8n-nodes-base.googleCalendar", "typeVersion": 1.3, "position": [ 4784, -208 ], "id": "3c32f96e-cd34-4be4-8c24-b4be7a8f29d9", "name": "Obtener entrenamientos ingles y espanol1", "credentials": { "googleCalendarOAuth2Api": { "id": "yEmGG4av5RxOK7wu", "name": "Eidan - Google Calendar account" } } }, { "parameters": { "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 169172567, "mode": "list", "cachedResultName": "Coordinadores RRHH", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=169172567" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 3616, -48 ], "id": "73089147-ba1f-4fb4-ac17-d5670b263fd8", "name": "Obtener coordinadores", "alwaysOutputData": false, "retryOnFail": true, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_coordinadores_rrhh_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ \"input\": $json.input }) }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3952, -48 ], "id": "231f396b-855a-4c50-8d6d-096018e6d2ac", "name": "Insertar/actualizar coordinadores a la bd" }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "input", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 3776, -48 ], "id": "e51bd2d5-22b5-46cf-b346-c1ba16bb5c34", "name": "Aggregate" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/sync_sesiones_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ \"input\": $json.input }) }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 5584, -304 ], "id": "3f4a0807-5f29-49cb-a851-41100e04f5bf", "name": "Insertar fechas1" }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "input", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 5440, -304 ], "id": "3ecbb0c7-f5f5-4644-9f42-8be9502e814d", "name": "Aggregate1" }, { "parameters": { "mode": "raw", "jsonOutput": "={\n \"meet_id\": \"{{ $json.id }}\",\n \"titulo\": \"{{ $json.titulo }}\",\n \"fecha_sesion\": \"{{ $json.fecha }}\",\n \"hora_inicio\": \"{{ $json.hora_inicio }}\",\n \"hora_fin\": \"{{ $json.hora_fin }}\",\n \"instructor\": \"{{ $json.Espanol || $json.English || null }}\",\n \"correo_instructor\": \"{{ $json.Correo || null }}\",\n \"enlace_reunion\": \"{{ $json.url }}\",\n \"idioma\": \"{{ $json.idioma }}\"\n}", "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 5296, -304 ], "id": "a099259d-36e3-48b6-aa77-d8132f33f85e", "name": "Edit Fields" }, { "parameters": { "mode": "combine", "advanced": true, "mergeByFields": { "values": [ { "field1": "Fecha", "field2": "fecha" } ] }, "options": {} }, "type": "n8n-nodes-base.merge", "typeVersion": 3.2, "position": [ 5152, -304 ], "id": "456bcbe4-cc98-48fc-bcd2-40f8961934ae", "name": "Unir datos" }, { "parameters": { "content": "## Actualizar instructores y fechas de las sesiones en supabase\n\nEste trigger se activa todos los dias a las 3pm", "height": 416, "width": 1152 }, "type": "n8n-nodes-base.stickyNote", "position": [ 4576, -480 ], "typeVersion": 1, "id": "b1eff313-9251-48db-a6f3-9f0e81c644a3", "name": "Sticky Note13" }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 15 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 4624, -288 ], "id": "6ef829bf-1d52-4093-bcc5-45d922393611", "name": "Schedule Trigger6" }, { "parameters": { "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 4784, -384 ], "id": "f1bf8c51-43cf-41d4-93c4-1a1d0a0dac7a", "name": "Obtener fechas e instructores", "alwaysOutputData": false, "retryOnFail": true, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "jsCode": "const months = [\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];\n\nfunction formatearFecha(dateTimeStr) {\n if (!dateTimeStr) return null;\n const datePart = dateTimeStr.split('T')[0];\n const [year, month, day] = datePart.split('-');\n return `${parseInt(day, 10)} ${months[parseInt(month, 10) - 1]}`;\n}\n\nfunction detectarIdioma(summary) {\n if (!summary) return null;\n if (summary.includes(\"#TheGLMWay Training\")) return \"EN\";\n if (summary.includes(\"Entrenamiento #TheGLMWay\")) return \"ES\";\n return null;\n}\n\nfunction formatearHora(dateTimeStr) {\n if (!dateTimeStr) return null;\n const timePart = dateTimeStr.split('T')[1];\n if (!timePart) return null;\n return timePart.substring(0, 5);\n}\n\nconst output = [];\n\nfor (const item of $input.all()) {\n const event = item.json;\n\n const startRaw = event.start?.dateTime || event.start?.date;\n const endRaw = event.end?.dateTime || event.end?.date;\n const url = event.conferenceData?.entryPoints?.[0]?.uri || null;\n const idioma = detectarIdioma(event.summary);\n\n // Ignorar eventos vacíos o sin datos esenciales\n if (!event.summary || !startRaw) {\n console.log(\"Evento ignorado (vacío):\", JSON.stringify(event));\n continue;\n }\n\n output.push({\n json: {\n id: event.id,\n titulo: event.summary,\n idioma: idioma,\n fecha: formatearFecha(startRaw),\n hora_inicio: formatearHora(startRaw),\n hora_fin: formatearHora(endRaw),\n url: url,\n descripcion: event.description || null\n }\n });\n}\n\nconsole.log(`Sesiones procesadas: ${output.length}`);\nreturn output;\n\n// Agrega esto antes del return output\nconst resumen = output.map(i => ({\n meet_id: i.json.meet_id,\n titulo: i.json.titulo,\n fecha_sesion: i.json.fecha_sesion,\n hora_inicio: i.json.hora_inicio,\n hora_fin: i.json.hora_fin,\n enlace_reunion: i.json.enlace_reunion,\n idioma: i.json.idioma\n}));\nconsole.log(JSON.stringify(resumen));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 4960, -208 ], "id": "8f80d9ca-1e4b-4753-b482-df7b0fd24f61", "name": "Formatear fecha y detectar idioma" }, { "parameters": { "jsCode": "const today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst sessions = $input.all();\n\n// Helper para parsear \"14 January\" → Date (año actual)\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\n// Formatear fecha como \"26 June\"\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\n// Iterar hasta encontrar la sesión que hace match con hoy\nlet matchedSession = null;\n\nfor (const item of sessions) {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n if (!sessionDate) continue;\n\n sessionDate.setHours(0, 0, 0, 0);\n\n if (sessionDate.getTime() === today.getTime()) {\n matchedSession = item;\n break;\n }\n}\n\nreturn [\n {\n json: {\n today: formatDate(today),\n foundSession: !!matchedSession,\n session: matchedSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 0, 2144 ], "id": "0db9e6a4-2e5e-4513-97fd-71d22aa90822", "name": "Calcular sesion mas cercana4" }, { "parameters": { "content": "## Añadir instructor al particpante", "height": 240, "width": 384, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ 1296, 2912 ], "typeVersion": 1, "id": "a9266141-49ab-41f7-b8ab-dc45e746ed1c", "name": "Sticky Note14" }, { "parameters": { "operation": "getAll", "tableId": "sesiones_glmway", "returnAll": true, "filters": { "conditions": [] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -192, 1504 ], "id": "a4fc1575-5326-467f-8b05-f8c9569cdca1", "name": "Obtener sesiones", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "getAll", "tableId": "coordinadores_rrhh_glmway", "returnAll": true, "filters": { "conditions": [ { "keyName": "estado", "condition": "eq", "keyValue": "=no_notificado" }, { "keyName": "pais", "condition": "eq", "keyValue": "={{ $json.sesion.participantes }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 464, 1488 ], "id": "0457dbf8-9c04-4f2d-9928-4f770eb51cc0", "name": "Obtener coordinadores1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "19e418dd-962b-4fe6-82db-19247f0e8165", "leftValue": "={{ $json.sesion.participantes }}", "rightValue": "", "operator": { "type": "object", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 208, 1504 ], "id": "334a5703-db8a-4a88-b528-8468ee61ddbc", "name": "Hay inscritos en la sesion?" }, { "parameters": { "jsCode": "// 1. Obtener la sesión del nodo anterior\nconst datosNodoAnterior = $(\"Calcular falta 48h o 24h1\").first().json;\nconst sesion = datosNodoAnterior.sesion;\nconst participantesPorPais = sesion?.participantes || {};\n\n// 2. Obtener todos los coordinadores\nconst coordinadores = $(\"Obtener coordinadores1\").all().map(i => i.json);\n\nconst resultado = [];\n\n// Función para quitar acentos y dejar en minúsculas (evita fallos de coincidencia)\nconst limpiarTexto = (texto) => \n texto ? texto.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\").trim() : \"\";\n\n// 3. Recorrer los países que tienen participantes en la sesión\nfor (const [paisParticipante] of Object.entries(participantesPorPais)) {\n\n // Buscar el coordinador cuyo país coincida limpiando acentos\n const coordinadorMatch = coordinadores.find(c => \n limpiarTexto(c.pais) === limpiarTexto(paisParticipante)\n );\n\n resultado.push({\n json: {\n pais: paisParticipante,\n coordinador: coordinadorMatch \n ? {\n nombre: coordinadorMatch.nombre,\n correo: coordinadorMatch.correo,\n pais_coordinador: coordinadorMatch.pais\n } \n : null,\n }\n });\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 656, 1488 ], "id": "3073d739-a2c7-4ba1-81bc-aeae266ad3ff", "name": "Matchear coordinador y pais inscrito" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "df25aa3e-d48f-4e52-ae1f-47678e954d52", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.participantes }}", "rightValue": "EN", "operator": { "type": "object", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 864, 2144 ], "id": "d1472787-4c2f-4e1d-8673-5c2368d469ab", "name": "Hay inscritos?" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee').item.json.department }}\",\n \"division\": \"{{ $('Get an employee').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2848, -336 ], "id": "4ab5f973-c2e1-410e-9212-8ed3b9d372e3", "name": "Registrar empleado a la sesion" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana1').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee').item.json.department }}\",\n \"division\": \"{{ $('Get an employee').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2848, -160 ], "id": "5e69165f-16a2-4f7a-ad48-d24c70f3c88b", "name": "Registrar empleado a la sesion1" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana2').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee1').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee1').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee1').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee1').item.json.department }}\",\n \"division\": \"{{ $('Get an employee1').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3280, 272 ], "id": "f3df197d-b557-45d7-94bb-76f3c300ae61", "name": "Registrar empleado a la sesion2" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana3').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee1').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee1').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee1').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee1').item.json.department }}\",\n \"division\": \"{{ $('Get an employee1').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3280, 448 ], "id": "23ac8709-b0ac-4bb6-911a-1e7641be075d", "name": "Registrar empleado a la sesion3" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Calcular sesion mas cercana').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2272, -336 ], "id": "ad0bb609-e224-4956-bf20-0d624f4ef3ae", "name": "Convertir fecha a espanol" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nconst fecha = $('Calcular sesion mas cercana1').first().json.session.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\nconst partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\nconst dia = partes[0];\nconst mes = partes[1];\nconst diaConSufijo = getOrdinalSuffix(dia);\n\nconst fechaFormateada = `${mes} ${diaConSufijo}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2272, -160 ], "id": "a1ad0e55-59e3-405e-b75d-d092112e9151", "name": "Convertir fecha a ingles" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Calcular sesion mas cercana2').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2688, 272 ], "id": "0d7870a9-0d82-49fe-96de-05c20164cffa", "name": "Convertir fecha a espanol1" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nfor (const item of $input.all()) {\n const fecha = $('Calcular sesion mas cercana3').first().json.session.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\n const partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\n const dia = partes[0];\n const mes = partes[1];\n const diaConSufijo = getOrdinalSuffix(dia);\n\n item.json.fechaFormateada = `${mes} ${diaConSufijo}`;\n}\n\nreturn $input.all();" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2688, 448 ], "id": "4abc2638-3ae3-4aba-b45f-0b60e73e3267", "name": "Convertir fecha a ingles1" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Guardar datos del empleado y sesion asignada').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2464, -336 ], "id": "740373c9-0145-41f4-a4b6-9dbb84ffbdaa", "name": "Cambiar zona horaria" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana1')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Guardar datos del empleado y sesion asignada1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2464, -160 ], "id": "77da2dc7-546b-4ab7-a7c7-fa621196b2d0", "name": "Cambiar zona horaria1" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana2')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Actualizar datos del empleado y sesion asignada').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2880, 272 ], "id": "bbd8c7de-64eb-4262-a77b-b7307ab9c0c6", "name": "Cambiar zona horaria2" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana3')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Actualizar datos del empleado y sesion asignada1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2880, 448 ], "id": "677acc91-b856-482e-aa2c-9b329221918a", "name": "Cambiar zona horaria3" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = \"19:00\";\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Loop Over Items1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1152, 752 ], "id": "67785f93-1b98-43f4-a72b-c94072ca22e6", "name": "Cambiar zona horaria4" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = \"19:00\";\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Loop Over Items1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1152, 960 ], "id": "b574514b-817a-4798-a44b-2eae1077e118", "name": "Cambiar zona horaria5" }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion", "keyValue": "={{ $json.fecha_sesion }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 608, 832 ], "id": "45d7c217-bfee-4ae8-97b1-b158ee7e3548", "name": "Obtener sesion", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "getAll", "tableId": "sesiones_glmway", "returnAll": true, "filters": { "conditions": [] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 2144 ], "id": "d34e225b-25bb-4a0a-845c-b9e274529000", "name": "Obtener sesion1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $('Get an employee').item.json.workEmail }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } }, { "id": "ec0276ab-208e-409b-8101-d06e535f541c", "leftValue": "={{ $('Get an employee').item.json.location }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 352, -144 ], "id": "a9fff247-d1b0-4314-ba8d-e7401086b771", "name": "Tiene correo y pais?" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $('Get an employee1').item.json.workEmail }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } }, { "id": "a245c081-ef08-4ba2-8164-2d2c35bd1e17", "leftValue": "={{ $('Get an employee1').item.json.location }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 752, 352 ], "id": "a2a81e91-f617-490a-b1ce-5737944fa23b", "name": "Tiene correo y pais?1" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Get an employee1').item.json.id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee1').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee1').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee1').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee1').item.json.location }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee1').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee1').item.json.jobTitle }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2496, 272 ], "id": "16d364da-e6fc-4943-bd64-f83ccab66b9f", "name": "Actualizar datos del empleado y sesion asignada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Get an employee1').item.json.id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee1').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee1').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee1').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee1').item.json.location }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee1').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee1').item.json.jobTitle }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2496, 448 ], "id": "f2aca2bd-e72d-4457-9a6b-c4b0f8bcc558", "name": "Actualizar datos del empleado y sesion asignada1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/conferenceRecords", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 64, 2752 ], "id": "602289b9-3c7d-4ced-b507-b27401ed9910", "name": "Obtener conferenceRecord", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAR2K6i8Y/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=yOTYTZ6rayK3NlOworCkaKMPCqssxjbokfKY3wFjeXg", "sendHeaders": true, "headerParameters": { "parameters": [ {} ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1840, 1824 ], "id": "11458855-2bd1-4778-81f6-efe07ee1ee8b", "name": "Enviar al espacio de prueba", "retryOnFail": true }, { "parameters": { "operation": "get", "contactId": "={{ $json.idLimpio }}", "fields": [ "emailAddresses", "names" ] }, "type": "n8n-nodes-base.googleContacts", "typeVersion": 1, "position": [ 528, 2144 ], "id": "1382bd89-9dd0-4fd5-a78d-853ac02840fb", "name": "Get a contact", "credentials": { "googleContactsOAuth2Api": { "id": "Qmeljx6s3HU998tB", "name": "Eidan - Google Contacts account" } } }, { "parameters": { "jsCode": "// 1. Obtenemos la lista de miembros del nodo anterior\n// Nota: Ajusta 'memberships' si tu JSON viene estructurado de otra forma\nconst memberships = $input.first().json.memberships || [];\n\n// 2. Mapeamos y limpiamos cada usuario\nconst usuariosLimpios = memberships.map(item => {\n const fullUserPath = item.member.name; // Ej: \"users/117120277440258194844\"\n \n // Reemplazamos \"users/\" por nada para dejar solo el número\n const idLimpio = fullUserPath.replace('users/', ''); \n \n return {\n json: {\n idOriginal: fullUserPath,\n idLimpio: idLimpio,\n role: item.role,\n type: item.member.type\n }\n };\n});\n\n// 3. Devolvemos la lista para que n8n los procese en lote\nreturn usuariosLimpios;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 352, 2144 ], "id": "41e5b9fd-598f-4dfb-b7f6-53d473ec1d71", "name": "Limpiar id" }, { "parameters": { "jsCode": "const today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst sessions = $input.all();\n\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n // Intenta parsear directamente o por partes\n const parsed = new Date(dateStr);\n if (!isNaN(parsed.getTime())) return parsed;\n\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\nlet matchedSession = null;\n\nfor (const item of sessions) {\n const rawDate = parseSessionDate(item.json.fecha_sesion);\n if (!rawDate || isNaN(rawDate.getTime())) continue;\n\n // Creamos una copia para no alterar la fecha original\n const sessionDate = new Date(rawDate.getTime());\n sessionDate.setHours(0, 0, 0, 0);\n\n if (sessionDate.getTime() === today.getTime()) {\n matchedSession = item;\n break;\n }\n}\n\nreturn [\n {\n json: {\n today: formatDate(today),\n foundSession: !!matchedSession,\n session: matchedSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 688, 2144 ], "id": "aa48e478-2800-4462-b8a5-fb4651701b2d", "name": "Unir datos2" }, { "parameters": { "url": "=https://chat.googleapis.com/v1/spaces/AAQAgX1mjaY/members", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleChatOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 192, 2144 ], "id": "7e8c9e23-1bfb-4111-983d-898eb43f4981", "name": "Obtener miembros", "retryOnFail": true, "credentials": { "googleChatOAuth2Api": { "id": "Tg9EZ8oKp4hqoWvX", "name": "Eidan - Chat account" } } }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Sin título\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con los datos de la sesión\nconst body = {\n text: `🔔 *Recordatorio de #TheGLMWay para hoy* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"🎓 Sesión de Capacitación\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Tema: ${titulo}
` +\n `Participantes inscritos: ${totalParticipantes} personas`\n }\n },\n {\n textParagraph: {\n text: `👉 Entrar a la reunión aquí`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2032 ], "id": "18d7cd2e-ba38-4c1b-b2e1-f3db9fe301d5", "name": "Formatear datos espanol" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Untitled\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con los datos de la sesión\nconst body = {\n text: `🔔 *#TheGLMWay Reminder for today* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"🎓 Training Session\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Topic: ${titulo}
` +\n `Registered participants: ${totalParticipantes} people`\n }\n },\n {\n textParagraph: {\n text: `👉 Join the meeting here`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 1872 ], "id": "36ad61bf-4d83-42f8-987e-8b8216115a67", "name": "Formatear datos ingles" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "EN", "operator": { "type": "string", "operation": "equals" }, "id": "a6a13143-17cd-4020-b789-726c8faae456" } ], "combinator": "and" } }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "5ffc2081-5b80-4d72-96fc-121dc727683a", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "ES", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" } } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ 1088, 1952 ], "id": "afe4c647-cec2-4cb4-84c5-4b52914ced09", "name": "Es espanol o ingles1" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "EN", "operator": { "type": "string", "operation": "equals" }, "id": "a6a13143-17cd-4020-b789-726c8faae456" } ], "combinator": "and" } }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "5ffc2081-5b80-4d72-96fc-121dc727683a", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "ES", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" } } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ 1104, 2288 ], "id": "17143de2-2245-45a8-b5db-06d73aa2104f", "name": "Es espanol o ingles" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Sin título\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con el aviso de que no hay participantes\nconst body = {\n text: `🔔 *Aviso de sesión sin participantes* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"⚠️ Sesión de Capacitación\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Tema: ${titulo}
\\n` +\n `No se han registrado participantes para la capacitación de hoy, por lo que no es necesario que te conectes.`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2368 ], "id": "953f5fb0-8eea-40f7-8910-a1da77516176", "name": "Formatear datos espanol1" }, { "parameters": { "jsCode": "// 1. Get session data from the \"Calcular sesion mas cercana4\" node\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Untitled\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Count participants by dynamically summing all countries\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Get contactId from the previous node to generate mentions\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Build the message body with the notice of no participants\nconst body = {\n text: `🔔 *No participants for today's training* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"⚠️ Training Session\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Topic: ${titulo}
\\n` +\n `No participants have registered for today's training, so you do not need to connect.`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2208 ], "id": "adb8c1b5-1696-49b1-aa2d-8b329846c007", "name": "Formatear datos ingles1" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAgX1mjaY/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=drBaE6ZeBbHhPKCmJd_odP3UcYcq4Ie64JXmbI29Vp8", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1520, 2128 ], "id": "db80a48f-bf0b-4b4e-a1d6-06c9da6c188c", "name": "Enviar notifacion a glmway notificaciones", "retryOnFail": true }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular falta 48h o 24h1\"\nconst sessionNode = $('Calcular falta 48h o 24h1').first();\nconst sesion = sessionNode?.json?.sesion || {}; // Leído desde la raíz del JSON\n\n// 2. Contar participantes y construir de forma dinámica la lista por país\nlet totalParticipantes = 0;\nlet listaParticipantesTexto = \"\";\n\nif (sesion.participantes) {\n Object.keys(sesion.participantes).forEach(pais => {\n const listaPais = sesion.participantes[pais];\n if (Array.isArray(listaPais) && listaPais.length > 0) {\n totalParticipantes += listaPais.length;\n \n // Añadir el encabezado del país\n listaParticipantesTexto += `
📍 ${pais} (${listaPais.length}):
`;\n \n // Listar cada participante de ese país\n listaPais.forEach(p => {\n listaParticipantesTexto += `• ${p.nombre} (${p.departamento || 'Sin Depto'} | ${p.division || 'Sin Division'})
`;\n });\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones de los coordinadores\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos3').all(); // Asegúrate de verificar si tu nodo se llama Unir datos3 o similar\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con formato Google Chat Card\nconst body = {\n text: `🔔 *Aviso para Coordinadores RRHH* \\nEstimados ${menciones}, aquí está el listado de personas inscritas para la capacitación de mañana.`,\n cardsV2: [\n {\n cardId: \"session-reminder-hr\",\n card: {\n header: {\n title: `🎓 Capacitación #TheGLMWay de mañana`,\n },\n sections: [\n {\n header: \"📈 Resumen de Asistencia\",\n widgets: [\n {\n textParagraph: {\n text: `Total inscritos: ${totalParticipantes} personas
` + \n listaParticipantesTexto\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1744, 1584 ], "id": "87ace248-4ea5-406f-89da-88d450ad413e", "name": "Formatear datos espanol2" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular falta 48h o 24h1\"\nconst sessionNode = $('Calcular falta 48h o 24h1').first();\nconst sesion = sessionNode?.json?.sesion || {}; // Leído desde la raíz del JSON\n\n// 2. Contar participantes y construir de forma dinámica la lista por país\nlet totalParticipantes = 0;\nlet listaParticipantesTexto = \"\";\n\nif (sesion.participantes) {\n Object.keys(sesion.participantes).forEach(pais => {\n const listaPais = sesion.participantes[pais];\n if (Array.isArray(listaPais) && listaPais.length > 0) {\n totalParticipantes += listaPais.length;\n \n // Añadir el encabezado del país\n listaParticipantesTexto += `
📍 ${pais} (${listaPais.length}):
`;\n \n // Listar cada participante de ese país\n listaPais.forEach(p => {\n listaParticipantesTexto += `• ${p.nombre} (${p.departamento || 'Sin Depto'} | ${p.division || 'Sin Division'})
`;\n });\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones de los coordinadores\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos3').all(); // Asegúrate de verificar si tu nodo se llama Unir datos3 o similar\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con formato Google Chat Card\nconst body = {\n text: `🔔 *HR Coordinator Notification* \\nDear ${menciones}, here is the list of people registered for tomorrow's session.`,\n cardsV2: [\n {\n cardId: \"session-reminder-hr\",\n card: {\n header: {\n title: `🎓 Tomorrow's #TheGLMWay Training`,\n },\n sections: [\n {\n header: \"📈 Attendance Summary\",\n widgets: [\n {\n textParagraph: {\n text: `Total registered: ${totalParticipantes} people
` + \n listaParticipantesTexto\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1744, 1408 ], "id": "bb4cbe19-9364-4c83-a309-5594d9c5a26b", "name": "Formatear datos ingles2" }, { "parameters": { "jsCode": "// Obtener todos los elementos que entran al nodo\nconst items = $input.all();\n\nconst hoy = new Date();\nhoy.setHours(0, 0, 0, 0);\n\nlet mejorItem = null;\nlet menorDiferencia = Infinity;\nlet mejorFechaHoyStr = '';\n\n// Recorrer cada sesión para calcular cuál es la más cercana\nfor (const item of items) {\n const fecha_sesion = item.json.fecha_sesion;\n if (!fecha_sesion) continue;\n\n // Crear la fecha de la sesión usando el año actual\n let sesion = new Date(`${fecha_sesion} ${hoy.getFullYear()}`);\n sesion.setHours(0, 0, 0, 0);\n\n // Si la fecha ya pasó este año, se toma la del año que viene\n if (sesion < hoy) {\n sesion = new Date(`${fecha_sesion} ${hoy.getFullYear() + 1}`);\n sesion.setHours(0, 0, 0, 0);\n }\n\n // Calcular diferencia en días\n const diferenciaDias = Math.floor((sesion - hoy) / (1000 * 60 * 60 * 24));\n\n // Si esta sesión es más cercana que las anteriores analizadas, la guardamos\n if (diferenciaDias < menorDiferencia) {\n menorDiferencia = diferenciaDias;\n mejorItem = item.json;\n mejorFechaHoyStr = hoy.toLocaleDateString('en-GB', {\n day: 'numeric',\n month: 'long'\n });\n }\n}\n\n// Si no se encontró ninguna sesión válida, no devuelve nada\nif (!mejorItem) return [];\n\n// Retorna únicamente la sesión más cercana encontrada\nreturn [\n {\n json: {\n sesion: mejorItem,\n fecha_hoy: mejorFechaHoyStr,\n diferenciaDias: menorDiferencia\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 0, 1504 ], "id": "47542a5b-ebe1-4e85-8229-bb9aa7e1b744", "name": "Calcular falta 48h o 24h1" }, { "parameters": { "operation": "get", "contactId": "={{ $json.idLimpio }}", "fields": [ "emailAddresses", "names" ] }, "type": "n8n-nodes-base.googleContacts", "typeVersion": 1, "position": [ 1200, 1488 ], "id": "f49640d2-f7a0-43da-b9e1-1da5dbe93a22", "name": "Get a contact1", "credentials": { "googleContactsOAuth2Api": { "id": "Qmeljx6s3HU998tB", "name": "Eidan - Google Contacts account" } } }, { "parameters": { "jsCode": "// 1. Obtenemos la lista de miembros del nodo anterior\n// Nota: Ajusta 'memberships' si tu JSON viene estructurado de otra forma\nconst memberships = $input.first().json.memberships || [];\n\n// 2. Mapeamos y limpiamos cada usuario\nconst usuariosLimpios = memberships.map(item => {\n const fullUserPath = item.member.name; // Ej: \"users/117120277440258194844\"\n \n // Reemplazamos \"users/\" por nada para dejar solo el número\n const idLimpio = fullUserPath.replace('users/', ''); \n \n return {\n json: {\n idOriginal: fullUserPath,\n idLimpio: idLimpio,\n role: item.role,\n type: item.member.type\n }\n };\n});\n\n// 3. Devolvemos la lista para que n8n los procese en lote\nreturn usuariosLimpios;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1024, 1488 ], "id": "c17d8ecc-45f9-4c03-a4d4-88d90ae8a3ec", "name": "Limpiar id1" }, { "parameters": { "jsCode": "// 1. Forzar la lectura del nodo de coordinadores\nconst itemsCoordinadores = $('Matchear coordinador y pais inscrito').all();\n\n// 2. Obtener todos los contactos cargados de \"Get a contact1\"\nconst contacts = $('Get a contact1').all();\n\nconst resultado = [];\n\n// Función para limpiar tildes, espacios y pasarlo a minúsculas\nconst limpiarTexto = (texto) => \n texto ? texto.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\").trim() : \"\";\n\n// 3. Procesar la lista de coordinadores\nfor (const item of itemsCoordinadores) {\n const coordinadorNombre = item.json.coordinador?.nombre;\n const paisCoordinador = item.json.pais; // Extraemos el país\n if (!coordinadorNombre) continue;\n\n const coordinadorClean = limpiarTexto(coordinadorNombre);\n\n // 4. Buscar coincidencias en los contactos de Google\n const matchingContacts = contacts.filter(c => {\n const displayName = c.json.names?.displayName;\n if (!displayName) return false;\n\n const displayNameClean = limpiarTexto(displayName);\n return displayNameClean === coordinadorClean || displayNameClean.includes(coordinadorClean) || coordinadorClean.includes(displayNameClean);\n });\n\n // 5. Guardar los resultados encontrados incluyendo el país\n for (const contactItem of matchingContacts) {\n resultado.push({\n json: {\n pais: paisCoordinador,\n nombre_detectado: contactItem.json.names.displayName,\n contactId: contactItem.json.contactId\n }\n });\n }\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1360, 1488 ], "id": "73de340f-189b-4963-bdf6-9b1bfd603cd6", "name": "Unir datos3" }, { "parameters": { "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/members", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleChatOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 864, 1488 ], "id": "949eb6ae-2aba-43d2-a262-f91313336d2f", "name": "Obtener miembros RRHH Notificaciones", "retryOnFail": true, "credentials": { "googleChatOAuth2Api": { "id": "Tg9EZ8oKp4hqoWvX", "name": "Eidan - Chat account" } } }, { "parameters": { "operation": "get", "tableId": "coordinadores_rrhh_glmway", "filters": { "conditions": [ { "keyName": "pais", "keyValue": "={{ $('Get an employee').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 736, -352 ], "id": "aeb15925-1828-426e-a437-809aee1df732", "name": "Obtener coordinador3", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "coordinadores_rrhh_glmway", "filters": { "conditions": [ { "keyName": "pais", "keyValue": "={{ $('Get an employee1').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1136, 256 ], "id": "e909b37d-a192-4845-b80f-fb1b245a6614", "name": "Obtener coordinador4", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/{{ $json.name }}/participants", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 432, 2752 ], "id": "c05fc7b5-5d4e-403b-aa67-49b7427f9b04", "name": "Obtener participantes", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion", "keyValue": "={{ $('Hora de la reunion').first().json.fechaCorta }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 832, 2752 ], "id": "e4115807-580d-4075-8d62-de14c174c43a", "name": "Obtener sesion2", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "// 1. Obtener la lista de nombres detectados en la reunión\nconst personasDetectadas = $('Detectar participantes en la sesion').all();\nconst nombresDetectados = personasDetectadas.map(item => item.json.displayName).filter(Boolean);\n\n// 2. Obtener los datos de la sesión (se toma el primer item del nodo)\nconst datosSesion = $('Obtener sesion2').first().json;\nconst participantesPorPais = datosSesion.participantes || {};\n\n// Normalizar texto: convierte a minúsculas y remueve acentos/diacríticos\nfunction normalizar(texto) {\n if (!texto) return \"\";\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .trim();\n}\n\n// Función para determinar si un nombre detectado corresponde a la persona registrada\nfunction esMismaPersona(nombreDetectado, nombreRegistrado) {\n const normDetectado = normalizar(nombreDetectado);\n const normRegistrado = normalizar(nombreRegistrado);\n\n if (!normDetectado || !normRegistrado) return false;\n\n // Separar en palabras ignorando conectores o palabras cortas (\"de\", \"del\", \"la\")\n const palabrasDetectadas = normDetectado.split(/\\s+/).filter(p => p.length > 2);\n const palabrasRegistradas = normRegistrado.split(/\\s+/).filter(p => p.length > 2);\n\n if (palabrasDetectadas.length === 0) return false;\n\n // Cuenta cuántas palabras del nombre detectado coinciden con el nombre completo registrado\n const coincidencias = palabrasDetectadas.filter(pDetectada => \n palabrasRegistradas.some(pRegistrada => pRegistrada.includes(pDetectada) || pDetectada.includes(pRegistrada))\n ).length;\n\n // Si el nombre detectado tiene 1 o 2 palabras, exige que al menos 1 o 2 coincidan.\n // Si tiene más de 2 palabras, exige al menos 2 coincidencias.\n if (palabrasDetectadas.length <= 2) {\n return coincidencias >= Math.min(palabrasDetectadas.length, 2);\n }\n return coincidencias >= 2;\n}\n\n// 3. Procesar a todos los participantes registrados por país\nconst todosLosParticipantes = [];\n\nObject.entries(participantesPorPais).forEach(([pais, listaPersonas]) => {\n if (Array.isArray(listaPersonas)) {\n listaPersonas.forEach(persona => {\n if (persona && persona.nombre && persona.nombre.trim() !== \"\") {\n\n // Comprobar si el participante asistió según la lista detectada\n const asistio = nombresDetectados.some(nombreDetectado =>\n esMismaPersona(nombreDetectado, persona.nombre)\n );\n\n todosLosParticipantes.push({\n pais: pais,\n nombreCompleto: persona.nombre,\n correo: persona.correo || \"\",\n division: persona.division || \"\",\n departamento: persona.departamento || \"\",\n asistio: asistio\n });\n }\n });\n }\n});\n\n// 4. Retornar respuesta unificada\nreturn [\n {\n json: {\n tituloSesion: datosSesion.titulo,\n fechaSesion: datosSesion.fecha_sesion,\n totalParticipantes: todosLosParticipantes.length,\n asistentes: todosLosParticipantes.filter(p => p.asistio).length,\n inasistentes: todosLosParticipantes.filter(p => !p.asistio).length,\n participantes: todosLosParticipantes\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1328, 2752 ], "id": "2e7c7d5a-13bf-40a0-bdf8-1f2f5b07188b", "name": "Buscar participantes" }, { "parameters": { "fieldToSplitOut": "participantes", "options": {} }, "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 1488, 2752 ], "id": "8b9471a9-f616-414d-988a-8f9914d72db3", "name": "Split Out" }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 19, "triggerAtMinute": 50 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -304, 2752 ], "id": "58146359-aef8-4a96-9f1c-9bc6987ce7f4", "name": "Schedule Trigger7" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion_inscrito", "condition": "eq", "keyValue": "={{ $json.fecha_sesion }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "instructor", "fieldValue": "={{ $json.instructor }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1328, 2992 ], "id": "982ec4df-b792-46b9-bce5-ab6e8709a2a8", "name": "Actualizar instructor de inscritos", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "nombre", "condition": "fullText", "searchFunction": "wfts", "keyValue": "={{ $json.nombreCompleto }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "asistio_evento_glmway", "fieldValue": "={{ $json.asistio }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1648, 2752 ], "id": "d93b4d14-106f-4d05-b397-78ec6d0dc522", "name": "Actualizar asistencia", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "// Obtener todos los items del nodo \"Obtener participantes\"\nconst items = $('Obtener participantes').all();\n\nconst resultado = [];\n\nfor (const item of items) {\n const participants = item.json.participants || [];\n\n for (const participant of participants) {\n if (participant.signedinUser) {\n resultado.push({\n json: {\n displayName: participant.signedinUser.displayName,\n user: participant.signedinUser.user\n }\n });\n }\n }\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 640, 2752 ], "id": "73c64bc3-4321-46d6-9d5b-ef74bd385b2c", "name": "Detectar participantes en la sesion" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.pais }}", "rightValue": "Jamaica", "operator": { "type": "string", "operation": "equals" } }, { "id": "32931394-f4ea-4055-b866-906a81988173", "leftValue": "={{ $json.pais }}", "rightValue": "Trinidad and Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "ea2a8466-96c6-460f-b08f-d23c06b2d18c", "leftValue": "={{ $json.pais }}", "rightValue": "Barbados", "operator": { "type": "string", "operation": "equals" } }, { "id": "28e49217-0c1a-4462-9642-676e54926d3e", "leftValue": "={{ $json.pais }}", "rightValue": "Saint Thomas", "operator": { "type": "string", "operation": "equals" } }, { "id": "c6a6aea5-48f4-44dc-92ca-a9f9de9cacf9", "leftValue": "={{ $json.pais }}", "rightValue": "St. Croix", "operator": { "type": "string", "operation": "equals" } }, { "id": "e6f52339-ea7c-462f-bdc2-8b7353160e4c", "leftValue": "={{ $json.pais }}", "rightValue": "Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "b308c2b6-53b4-4d49-b540-cdc03e36528b", "leftValue": "={{ $json.pais }}", "rightValue": "Guyana", "operator": { "type": "string", "operation": "equals" } }, { "id": "35a50a33-a2b5-4116-9336-11300357569e", "leftValue": "={{ $json.pais }}", "rightValue": "Aruba", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 2192, 2752 ], "id": "5df50d37-798a-42f8-ab7b-2ae3f05610fd", "name": "Pais?4" }, { "parameters": { "jsCode": "// Retorna solo el primer nombre de cada participante\nconst items = $input.all();\n\nreturn items.map(item => {\n const nombreCompleto = item.json.nombre || \"\";\n const primerNombre = nombreCompleto.trim().split(/\\s+/)[0] || \"\";\n\n return {\n json: {\n ...item.json,\n primerNombre\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2048, 2752 ], "id": "9c046113-3694-40f9-819c-42122ec117e5", "name": "Cortar nombre" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "085e7943-f198-4ef9-acab-3c06a3e18cdc", "leftValue": "={{ $json.asistio_evento_glmway }}", "rightValue": false, "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 1824, 2752 ], "id": "a2011c37-b133-431b-b8ff-41b6a4bb4f10", "name": "Asistio?" }, { "parameters": { "jsCode": "// Convierte fechas ISO, incluyendo T24:00:00 -> día siguiente T00:00:00\nfunction parseISO(iso) {\n if (!iso.includes(\"T24:\")) {\n return new Date(iso).getTime();\n }\n\n const [datePart, timePart] = iso.split(\"T\");\n const nextDay = new Date(datePart + \"T00:00:00Z\");\n nextDay.setUTCDate(nextDay.getUTCDate() + 1);\n\n const fixedIso = nextDay.toISOString().split(\"T\")[0] + \"T\" + timePart.replace(\"24:\", \"00:\");\n return new Date(fixedIso).getTime();\n}\n\n// Rango objetivo\nconst reunion = $('Hora de la reunion').first().json;\nconst targetStart = parseISO(reunion.startTime);\nconst targetEnd = parseISO(reunion.endTime);\n\n// Fecha objetivo (YYYY-MM-DD)\nconst targetDate = reunion.startTime.split(\"T\")[0];\n\n// Conferencias\nconst conferences = $('Obtener conferenceRecord').first().json.conferenceRecords;\n\n// Filtrar solo conferencias del mismo día\nconst resultado = conferences\n .filter(conf => conf.startTime.split(\"T\")[0] === targetDate)\n .map(conf => {\n const confStart = parseISO(conf.startTime);\n const confEnd = parseISO(conf.endTime);\n\n let distancia;\n\n if (confStart <= targetEnd && confEnd >= targetStart) {\n distancia = 0;\n } else {\n distancia = Math.min(\n Math.abs(confStart - targetEnd),\n Math.abs(confEnd - targetStart)\n );\n }\n\n return {\n json: {\n name: conf.name,\n startTime: conf.startTime,\n endTime: conf.endTime,\n distanciaMs: distancia\n }\n };\n })\n .sort((a, b) => a.json.distanciaMs - b.json.distanciaMs);\n\n// Retornar sin el campo de distancia\nreturn resultado.map(item => ({\n json: {\n name: item.json.name,\n startTime: item.json.startTime,\n endTime: item.json.endTime\n }\n}));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 240, 2752 ], "id": "881e05b0-c9fd-4799-b828-395b99f92a88", "name": "Buscar sesion con hora UTC" }, { "parameters": { "httpMethod": "POST", "path": "evaluacion-glmway", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -320, 3088 ], "id": "fe7c0429-6070-4181-ad6d-1a5a4888ce66", "name": "Webhook1", "webhookId": "14f1d226-12da-42c2-90d1-4d8fd5620cae" }, { "parameters": { "content": "## Guardar conteo de evaluaciones han sido resueltas", "height": 240, "width": 608, "color": 4 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 3008 ], "typeVersion": 1, "id": "7d34e6af-6b75-4780-9f70-848d2045b123", "name": "Sticky Note7" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/incrementar_evaluaciones_resueltas_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -112, 3088 ], "id": "59013746-bac2-4c90-a39e-3d7835ab6c31", "name": "Incrementar conteo de evaluaciones respondidas" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/incrementar_evaluaciones_enviadas_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2816, 2768 ], "id": "5b1e1192-2e9b-44b2-9303-194b6266202b", "name": "Incrementar conteo de evaluaciones enviadas" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1952, 1408 ], "id": "5d50cef9-0ebb-4f28-8deb-69c7feb6f62e", "name": "Enviar notificacion a rrhh notificaciones", "retryOnFail": true }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1952, 1584 ], "id": "c83590cd-6e98-4e2d-81f6-6e2f204a948d", "name": "Enviar notificacion a rrhh notificaciones1", "retryOnFail": true }, { "parameters": { "url": "=https://meet.googleapis.com/v2/conferenceRecords", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": { "pagination": { "pagination": { "parameters": { "parameters": [ { "name": "pageToken", "value": "={{ $response.body.nextPageToken }}" } ] }, "paginationCompleteWhen": "other", "completeExpression": "={{ !$response.body.nextPageToken }}" } } } }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 592, 3472 ], "id": "a13dbc58-f474-4eb8-aebb-68e1bf97ff42", "name": "Obtener conferenceRecord1", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/{{ $json.data[5].name }}/participants", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1264, 3472 ], "id": "08659d49-c234-447c-9262-06f6e099b243", "name": "Obtener participantes1", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "method": "POST", "url": "https://backend.composio.dev/api/v3/tools/execute/googlemeet_list_conference_records", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "x-api-key", "value": "ak_LlFK0KrKzU9LBNqvePo9" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "{\n \"entity_id\": \"pg-test-7d008927-9e8c-4d83-afe9-a77b7dc8efd7\",\n \"connected_account_id\": \"ca_zJ0wM5hvfThQ\",\n \"arguments\": {}\n}", "options": { "pagination": { "pagination": { "parameters": { "parameters": [ { "name": "pageToken", "value": "={{ $response.body.nextPageToken }}" } ] }, "paginationCompleteWhen": "other", "completeExpression": "={{ !$response.body.nextPageToken }}" } } } }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1056, 3760 ], "id": "48c3fbf9-48ec-4fd5-8ad0-157f4549d6ee", "name": "Composio - Obtener registro" }, { "parameters": { "method": "POST", "url": "https://backend.composio.dev/api/v3/tools/execute/GOOGLEMEET_LIST_PARTICIPANT_SESSIONS", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "x-api-key", "value": "ak_LlFK0KrKzU9LBNqvePo9" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"entity_id\": \"pg-test-7d008927-9e8c-4d83-afe9-a77b7dc8efd7\",\n \"connected_account_id\": \"ca_zJ0wM5hvfThQ\",\n \"arguments\": {\n \"parent\": \"{{ $json.data.conferenceRecords[9].name }}\"\n }\n} ", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1280, 3760 ], "id": "fef3abc8-4b8a-47a2-9508-61793ec02566", "name": "Composio - Obtener participantes" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Pais?2').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 960, 752 ], "id": "e41d24f2-67d7-410a-a0b6-87a0302b6c11", "name": "Convertir fecha a espanol2" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nconst fecha = $('Pais?2').first().json.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\nconst partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\nconst dia = partes[0];\nconst mes = partes[1];\nconst diaConSufijo = getOrdinalSuffix(dia);\n\nconst fechaFormateada = `${mes} ${diaConSufijo}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 960, 960 ], "id": "c452dd02-ecb8-4b2a-a179-bbd08faf01ef", "name": "Convertir fecha a ingles2" }, { "parameters": { "fieldToSplitOut": "conferenceRecords", "options": {} }, "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 800, 3472 ], "id": "9db65bec-8550-488d-ab1c-b5559878c381", "name": "Split Out1" }, { "parameters": { "aggregate": "aggregateAllItemData", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 992, 3472 ], "id": "7bbaf7f0-2451-4120-b94a-56e8628fff9e", "name": "Aggregate2" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1776, 2128 ], "id": "a2c3da31-9918-42f2-a71b-9fdfdc09d63d", "name": "Enviar notificacion a rrhh notificaciones2", "retryOnFail": true }, { "parameters": { "jsCode": "const timestamp = $input.first().json.timestamp;\n\n// Extraer solo la fecha YYYY-MM-DD\nconst fecha = timestamp.split(\"T\")[0];\n\nconst startTime = fecha + \"T22:50:24.833266Z\";\nconst endTime = fecha + \"T24:00:00.833266Z\";\n\n// Crear objeto Date forzando la hora a mediodía para evitar saltos de zona horaria\nconst fechaObj = new Date(fecha + \"T12:00:00Z\");\n\nconst dia = fechaObj.getUTCDate();\nconst mes = fechaObj.toLocaleString(\"en-US\", { month: \"long\", timeZone: \"UTC\" });\n\nconst fechaCorta = `${dia} ${mes}`;\n\nreturn [\n {\n json: {\n startTime,\n endTime,\n fechaCorta\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -112, 2752 ], "id": "e78ee155-4c33-419e-a3f8-1ef0631357a6", "name": "Hora de la reunion" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Cortar nombre').item.json.empleado_id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "estado", "fieldValue": "evaluacion_enviada" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2624, 2768 ], "id": "b7c02e2f-1382-4086-9059-cf75fee9d278", "name": "Actualizar estado a evaluacion_enviada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } } ], "connections": { "Webhook": { "main": [ [ { "node": "Get an employee", "type": "main", "index": 0 } ] ] }, "When clicking ‘Execute workflow’": { "main": [ [ { "node": "Valores", "type": "main", "index": 0 } ] ] }, "Obtener archivo": { "main": [ [ { "node": "Get a workflow1", "type": "main", "index": 0 } ], [ { "node": "Get a workflow2", "type": "main", "index": 0 } ] ] }, "Get a workflow1": { "main": [ [ { "node": "Code in JavaScript2", "type": "main", "index": 0 } ] ] }, "Get a workflow2": { "main": [ [ { "node": "Code in JavaScript4", "type": "main", "index": 0 } ] ] }, "Valores": { "main": [ [ { "node": "Obtener archivo", "type": "main", "index": 0 } ] ] }, "Code in JavaScript2": { "main": [ [ { "node": "Actualizar archivo", "type": "main", "index": 0 } ] ] }, "Code in JavaScript4": { "main": [ [ { "node": "Subir archivo", "type": "main", "index": 0 } ] ] }, "Get an employee": { "main": [ [ { "node": "Informacion extra del empleado", "type": "main", "index": 0 } ] ] }, "Informacion extra del empleado": { "main": [ [ { "node": "Calcular fecha hireDate", "type": "main", "index": 0 } ] ] }, "Entra hoy?": { "main": [ [ { "node": "Obtener coordinador3", "type": "main", "index": 0 } ], [ { "node": "Insertar a inscritos (inactivo)", "type": "main", "index": 0 } ] ] }, "Calcular fecha hireDate": { "main": [ [ { "node": "Tiene correo y pais?", "type": "main", "index": 0 } ] ] }, "Hay coordinador?": { "main": [ [ { "node": "Pais?", "type": "main", "index": 0 } ], [ { "node": "Alerta no hay coordinador RRHH", "type": "main", "index": 0 } ] ] }, "Schedule Trigger1": { "main": [ [ { "node": "Obtener inactivos", "type": "main", "index": 0 } ] ] }, "Get an employee1": { "main": [ [ { "node": "Informacion extra del empleado1", "type": "main", "index": 0 } ] ] }, "Informacion extra del empleado1": { "main": [ [ { "node": "Calcular fecha hireDate1", "type": "main", "index": 0 } ] ] }, "Loop Over Items": { "main": [ [], [ { "node": "Get an employee1", "type": "main", "index": 0 } ] ] }, "Calcular fecha hireDate1": { "main": [ [ { "node": "Tiene correo y pais?1", "type": "main", "index": 0 } ] ] }, "Entra hoy?1": { "main": [ [ { "node": "Obtener coordinador4", "type": "main", "index": 0 } ], [ { "node": "Wait2", "type": "main", "index": 0 } ] ] }, "Pais?1": { "main": [ [ { "node": "Crear variable idioma ES1", "type": "main", "index": 0 } ], [ { "node": "Crear variable idioma EN1", "type": "main", "index": 0 } ] ] }, "Hay coordinador?1": { "main": [ [ { "node": "Pais?1", "type": "main", "index": 0 } ], [ { "node": "Alerta no hay coordinador RRHH1", "type": "main", "index": 0 } ] ] }, "Pais?": { "main": [ [ { "node": "Crear variable idioma ES", "type": "main", "index": 0 } ], [ { "node": "Crear variable idioma EN", "type": "main", "index": 0 } ] ] }, "Send a message ingles1": { "main": [ [ { "node": "Registrar empleado a la sesion3", "type": "main", "index": 0 } ] ] }, "Send a message espanol1": { "main": [ [ { "node": "Registrar empleado a la sesion2", "type": "main", "index": 0 } ] ] }, "Wait": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Schedule Trigger2": { "main": [ [ { "node": "Obtener notificados", "type": "main", "index": 0 } ] ] }, "Obtener inactivos": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Loop Over Items1": { "main": [ [], [ { "node": "Calcular falta 24h o es el mismo dia", "type": "main", "index": 0 } ] ] }, "Pais?2": { "main": [ [ { "node": "Convertir fecha a espanol2", "type": "main", "index": 0 } ], [ { "node": "Convertir fecha a ingles2", "type": "main", "index": 0 } ] ] }, "Send a message espanol2": { "main": [ [ { "node": "Actualizar estado a recordado", "type": "main", "index": 0 } ] ] }, "Send a message ingles2": { "main": [ [ { "node": "Actualizar estado a recordado", "type": "main", "index": 0 } ] ] }, "Crear variable idioma ES": { "main": [ [ { "node": "Obtener sesiones español", "type": "main", "index": 0 } ] ] }, "Crear variable idioma EN": { "main": [ [ { "node": "Obtener sesiones ingles", "type": "main", "index": 0 } ] ] }, "Obtener sesiones español": { "main": [ [ { "node": "Calcular sesion mas cercana", "type": "main", "index": 0 } ] ] }, "Obtener sesiones ingles": { "main": [ [ { "node": "Calcular sesion mas cercana1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana": { "main": [ [ { "node": "Guardar datos del empleado y sesion asignada", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana1": { "main": [ [ { "node": "Guardar datos del empleado y sesion asignada1", "type": "main", "index": 0 } ] ] }, "Crear variable idioma ES1": { "main": [ [ { "node": "Obtener sesiones español1", "type": "main", "index": 0 } ] ] }, "Crear variable idioma EN1": { "main": [ [ { "node": "Obtener sesiones ingles1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana2": { "main": [ [ { "node": "Actualizar datos del empleado y sesion asignada", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana3": { "main": [ [ { "node": "Actualizar datos del empleado y sesion asignada1", "type": "main", "index": 0 } ] ] }, "Guardar datos del empleado y sesion asignada": { "main": [ [ { "node": "Convertir fecha a espanol", "type": "main", "index": 0 } ] ] }, "Guardar datos del empleado y sesion asignada1": { "main": [ [ { "node": "Convertir fecha a ingles", "type": "main", "index": 0 } ] ] }, "Obtener sesiones español1": { "main": [ [ { "node": "Calcular sesion mas cercana2", "type": "main", "index": 0 } ] ] }, "Obtener sesiones ingles1": { "main": [ [ { "node": "Calcular sesion mas cercana3", "type": "main", "index": 0 } ] ] }, "Alerta no hay coordinador RRHH1": { "main": [ [ { "node": "Pais?1", "type": "main", "index": 0 } ] ] }, "Wait2": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Obtener notificados": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Falta 24h para el evento?": { "main": [ [ { "node": "Obtener sesion", "type": "main", "index": 0 } ], [ { "node": "Wait1", "type": "main", "index": 0 } ] ] }, "Wait1": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Actualizar estado a recordado": { "main": [ [ { "node": "Wait1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger3": { "main": [ [ { "node": "Obtener sesiones", "type": "main", "index": 0 } ] ] }, "Pais?3": { "main": [ [ { "node": "Formatear datos ingles2", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol2", "type": "main", "index": 0 } ] ] }, "Calcular falta 24h o es el mismo dia": { "main": [ [ { "node": "Falta 24h para el evento?", "type": "main", "index": 0 } ] ] }, "Schedule Trigger4": { "main": [ [ { "node": "Obtener entrenamientos ingles y espanol", "type": "main", "index": 0 } ] ] }, "Insertar fechas": { "main": [ [] ] }, "Wait4": { "main": [ [ { "node": "Insertar fechas", "type": "main", "index": 0 } ] ] }, "Borrar fechas": { "main": [ [ { "node": "Wait4", "type": "main", "index": 0 } ] ] }, "Send a message ingles4": { "main": [ [ { "node": "Actualizar estado a evaluacion_enviada", "type": "main", "index": 0 } ] ] }, "Send a message espanol4": { "main": [ [ { "node": "Actualizar estado a evaluacion_enviada", "type": "main", "index": 0 } ] ] }, "Obtener entrenamientos ingles y espanol": { "main": [ [ { "node": "Formatear fecha", "type": "main", "index": 0 } ] ] }, "Formatear fecha": { "main": [ [ { "node": "Borrar fechas", "type": "main", "index": 0 } ] ] }, "Schedule Trigger5": { "main": [ [ { "node": "Obtener coordinadores", "type": "main", "index": 0 } ] ] }, "Obtener entrenamientos ingles y espanol1": { "main": [ [ { "node": "Formatear fecha y detectar idioma", "type": "main", "index": 0 } ] ] }, "Obtener coordinadores": { "main": [ [ { "node": "Aggregate", "type": "main", "index": 0 } ] ] }, "Aggregate": { "main": [ [ { "node": "Insertar/actualizar coordinadores a la bd", "type": "main", "index": 0 } ] ] }, "Aggregate1": { "main": [ [ { "node": "Insertar fechas1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger6": { "main": [ [ { "node": "Obtener fechas e instructores", "type": "main", "index": 0 }, { "node": "Obtener entrenamientos ingles y espanol1", "type": "main", "index": 0 } ] ] }, "Formatear fecha y detectar idioma": { "main": [ [ { "node": "Unir datos", "type": "main", "index": 1 } ] ] }, "Obtener fechas e instructores": { "main": [ [ { "node": "Unir datos", "type": "main", "index": 0 } ] ] }, "Unir datos": { "main": [ [ { "node": "Edit Fields", "type": "main", "index": 0 } ] ] }, "Edit Fields": { "main": [ [ { "node": "Aggregate1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger": { "main": [ [ { "node": "Obtener sesion1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana4": { "main": [ [ { "node": "Obtener miembros", "type": "main", "index": 0 } ] ] }, "Obtener sesiones": { "main": [ [ { "node": "Calcular falta 48h o 24h1", "type": "main", "index": 0 } ] ] }, "Obtener coordinadores1": { "main": [ [ { "node": "Matchear coordinador y pais inscrito", "type": "main", "index": 0 } ] ] }, "Hay inscritos en la sesion?": { "main": [ [ { "node": "Obtener coordinadores1", "type": "main", "index": 0 } ], [] ] }, "Matchear coordinador y pais inscrito": { "main": [ [ { "node": "Obtener miembros RRHH Notificaciones", "type": "main", "index": 0 } ] ] }, "Hay inscritos?": { "main": [ [ { "node": "Es espanol o ingles1", "type": "main", "index": 0 } ], [ { "node": "Es espanol o ingles", "type": "main", "index": 0 } ] ] }, "Registrar empleado a la sesion": { "main": [ [] ] }, "Registrar empleado a la sesion1": { "main": [ [] ] }, "Registrar empleado a la sesion2": { "main": [ [ { "node": "Wait", "type": "main", "index": 0 } ] ] }, "Registrar empleado a la sesion3": { "main": [ [ { "node": "Wait", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol": { "main": [ [ { "node": "Cambiar zona horaria", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles": { "main": [ [ { "node": "Cambiar zona horaria1", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol1": { "main": [ [ { "node": "Cambiar zona horaria2", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles1": { "main": [ [ { "node": "Cambiar zona horaria3", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria": { "main": [ [ { "node": "Send a message espanol", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria1": { "main": [ [ { "node": "Send a message ingles", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria2": { "main": [ [ { "node": "Send a message espanol1", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria3": { "main": [ [ { "node": "Send a message ingles1", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria5": { "main": [ [ { "node": "Send a message ingles2", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria4": { "main": [ [ { "node": "Send a message espanol2", "type": "main", "index": 0 } ] ] }, "Obtener sesion": { "main": [ [ { "node": "Pais?2", "type": "main", "index": 0 } ] ] }, "Obtener sesion1": { "main": [ [ { "node": "Calcular sesion mas cercana4", "type": "main", "index": 0 } ] ] }, "Tiene correo y pais?": { "main": [ [ { "node": "Entra hoy?", "type": "main", "index": 0 } ], [ { "node": "Insertar a inscritos (inactivo)", "type": "main", "index": 0 } ] ] }, "Tiene correo y pais?1": { "main": [ [ { "node": "Entra hoy?1", "type": "main", "index": 0 } ], [ { "node": "Wait2", "type": "main", "index": 0 } ] ] }, "Send a message espanol": { "main": [ [ { "node": "Registrar empleado a la sesion", "type": "main", "index": 0 } ] ] }, "Send a message ingles": { "main": [ [ { "node": "Registrar empleado a la sesion1", "type": "main", "index": 0 } ] ] }, "Actualizar datos del empleado y sesion asignada": { "main": [ [ { "node": "Convertir fecha a espanol1", "type": "main", "index": 0 } ] ] }, "Actualizar datos del empleado y sesion asignada1": { "main": [ [ { "node": "Convertir fecha a ingles1", "type": "main", "index": 0 } ] ] }, "Alerta no hay coordinador RRHH": { "main": [ [ { "node": "Pais?", "type": "main", "index": 0 } ] ] }, "Obtener conferenceRecord": { "main": [ [ { "node": "Buscar sesion con hora UTC", "type": "main", "index": 0 } ] ] }, "Limpiar id": { "main": [ [ { "node": "Get a contact", "type": "main", "index": 0 } ] ] }, "Get a contact": { "main": [ [ { "node": "Unir datos2", "type": "main", "index": 0 } ] ] }, "Unir datos2": { "main": [ [ { "node": "Hay inscritos?", "type": "main", "index": 0 } ] ] }, "Obtener miembros": { "main": [ [ { "node": "Limpiar id", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Es espanol o ingles1": { "main": [ [ { "node": "Formatear datos ingles", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol", "type": "main", "index": 0 } ] ] }, "Es espanol o ingles": { "main": [ [ { "node": "Formatear datos ingles1", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol1", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles1": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol1": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles2": { "main": [ [ { "node": "Enviar notificacion a rrhh notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol2": { "main": [ [ { "node": "Enviar notificacion a rrhh notificaciones1", "type": "main", "index": 0 } ] ] }, "Calcular falta 48h o 24h1": { "main": [ [ { "node": "Hay inscritos en la sesion?", "type": "main", "index": 0 } ] ] }, "Get a contact1": { "main": [ [ { "node": "Unir datos3", "type": "main", "index": 0 } ] ] }, "Limpiar id1": { "main": [ [ { "node": "Get a contact1", "type": "main", "index": 0 } ] ] }, "Unir datos3": { "main": [ [ { "node": "Pais?3", "type": "main", "index": 0 } ] ] }, "Obtener miembros RRHH Notificaciones": { "main": [ [ { "node": "Limpiar id1", "type": "main", "index": 0 } ] ] }, "Obtener coordinador3": { "main": [ [ { "node": "Hay coordinador?", "type": "main", "index": 0 } ] ] }, "Obtener coordinador4": { "main": [ [ { "node": "Hay coordinador?1", "type": "main", "index": 0 } ] ] }, "Obtener sesion2": { "main": [ [ { "node": "Buscar participantes", "type": "main", "index": 0 }, { "node": "Actualizar instructor de inscritos", "type": "main", "index": 0 } ] ] }, "Obtener participantes": { "main": [ [ { "node": "Detectar participantes en la sesion", "type": "main", "index": 0 } ] ] }, "Buscar participantes": { "main": [ [ { "node": "Split Out", "type": "main", "index": 0 } ] ] }, "Split Out": { "main": [ [ { "node": "Actualizar asistencia", "type": "main", "index": 0 } ] ] }, "Schedule Trigger7": { "main": [ [ { "node": "Hora de la reunion", "type": "main", "index": 0 } ] ] }, "Detectar participantes en la sesion": { "main": [ [ { "node": "Obtener sesion2", "type": "main", "index": 0 } ] ] }, "Actualizar asistencia": { "main": [ [ { "node": "Asistio?", "type": "main", "index": 0 } ] ] }, "Pais?4": { "main": [ [ { "node": "Send a message ingles4", "type": "main", "index": 0 } ], [ { "node": "Send a message espanol4", "type": "main", "index": 0 } ] ] }, "Asistio?": { "main": [ [ { "node": "Cortar nombre", "type": "main", "index": 0 } ] ] }, "Cortar nombre": { "main": [ [ { "node": "Pais?4", "type": "main", "index": 0 } ] ] }, "Buscar sesion con hora UTC": { "main": [ [ { "node": "Obtener participantes", "type": "main", "index": 0 } ] ] }, "Webhook1": { "main": [ [ { "node": "Incrementar conteo de evaluaciones respondidas", "type": "main", "index": 0 } ] ] }, "Enviar notificacion a rrhh notificaciones": { "main": [ [] ] }, "Enviar notificacion a rrhh notificaciones1": { "main": [ [] ] }, "Obtener conferenceRecord1": { "main": [ [ { "node": "Split Out1", "type": "main", "index": 0 } ] ] }, "Composio - Obtener registro": { "main": [ [ { "node": "Composio - Obtener participantes", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol2": { "main": [ [ { "node": "Cambiar zona horaria4", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles2": { "main": [ [ { "node": "Cambiar zona horaria5", "type": "main", "index": 0 } ] ] }, "Split Out1": { "main": [ [ { "node": "Aggregate2", "type": "main", "index": 0 } ] ] }, "Aggregate2": { "main": [ [ { "node": "Obtener participantes1", "type": "main", "index": 0 } ] ] }, "Hora de la reunion": { "main": [ [ { "node": "Obtener conferenceRecord", "type": "main", "index": 0 } ] ] }, "Obtener participantes1": { "main": [ [] ] }, "Actualizar estado a evaluacion_enviada": { "main": [ [ { "node": "Incrementar conteo de evaluaciones enviadas", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1", "binaryMode": "separate", "timeSavedMode": "fixed", "timezone": "America/Santo_Domingo", "callerPolicy": "workflowsFromSameOwner", "availableInMCP": false, "errorWorkflow": "lX5ITf9s4TSQglsM" }, "staticData": { "node:Gmail Trigger": { "Gmail Trigger": { "lastTimeChecked": 1781290702 } }, "node:Schedule Trigger": { "recurrenceRules": [] }, "node:Schedule Trigger1": { "recurrenceRules": [] }, "node:Comenzo evento ingles": { "lastTimeChecked": "2026-07-27T18:58:50Z" }, "node:Comenzo evento español": { "lastTimeChecked": "2026-07-27T18:58:50Z" }, "node:Termino evento español": { "lastTimeChecked": "2026-07-27T18:58:50Z" }, "node:Termino evento ingles": { "lastTimeChecked": "2026-07-27T18:58:51Z" }, "node:Prueba": { "lastTimeChecked": "2026-07-27T18:58:50Z" }, "node:Schedule Trigger2": { "recurrenceRules": [] }, "node:Schedule Trigger3": { "recurrenceRules": [] }, "node:Schedule Trigger4": { "recurrenceRules": [] }, "node:Schedule Trigger5": { "recurrenceRules": [] }, "node:Schedule Trigger6": { "recurrenceRules": [] }, "node:Prueba1": { "lastTimeChecked": "2026-07-27T18:58:50Z" }, "node:Inicio evento español1": { "lastTimeChecked": "2026-07-27T18:58:51Z" }, "node:Termino evento español1": { "lastTimeChecked": "2026-07-27T18:00:12Z" }, "node:Schedule Trigger7": { "recurrenceRules": [] }, "node:Termino evento": { "lastTimeChecked": "2026-08-27T17:17:11Z" }, "node:Termino evento1": { "lastTimeChecked": "2026-08-27T17:17:11Z" } }, "meta": { "templateCredsSetupCompleted": true }, "pinData": { "Schedule Trigger1": [ { "json": { "timestamp": "2026-08-11T12:00:24.018-04:00", "Readable date": "August 11th 2026, 12:00:24 pm", "Readable time": "12:00:24 pm", "Day of week": "Tuesday", "Year": "2026", "Month": "August", "Day of month": "11", "Hour": "12", "Minute": "00", "Second": "24", "Timezone": "America/Santo_Domingo (UTC-04:00)" }, "pairedItem": { "item": 0 } } ], "Schedule Trigger": [ { "json": { "timestamp": "2026-08-26T16:00:56.008-04:00", "Readable date": "August 26th 2026, 4:00:56 pm", "Readable time": "4:00:56 pm", "Day of week": "Wednesday", "Year": "2026", "Month": "August", "Day of month": "26", "Hour": "16", "Minute": "00", "Second": "56", "Timezone": "America/Santo_Domingo (UTC-04:00)" }, "pairedItem": { "item": 0 } } ] }, "versionId": "f657df3d-e5b6-445e-ad75-df66da81ebf3", "activeVersionId": "f657df3d-e5b6-445e-ad75-df66da81ebf3", "versionCounter": 8051, "triggerCount": 10, "shared": [ { "updatedAt": "2026-06-08T13:50:12.177Z", "createdAt": "2026-06-08T13:50:12.177Z", "role": "workflow:owner", "workflowId": "F1iPg8hktNAebZua", "projectId": "0bH6HfYEL8n6SDmr", "project": { "updatedAt": "2026-04-22T14:25:04.701Z", "createdAt": "2026-04-22T14:22:54.790Z", "id": "0bH6HfYEL8n6SDmr", "name": "Eidan Then ", "type": "personal", "icon": null, "description": null, "creatorId": "de14e7e5-491b-4983-abb2-f88af42e92fd" } } ], "tags": [], "activeVersion": { "updatedAt": "2026-08-27T17:54:10.000Z", "createdAt": "2026-08-27T17:53:55.742Z", "versionId": "f657df3d-e5b6-445e-ad75-df66da81ebf3", "workflowId": "F1iPg8hktNAebZua", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "glmway", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -352, -144 ], "id": "4cff954f-86fd-4835-8463-b083e3a66f35", "name": "Webhook", "webhookId": "2dea176c-88de-41b6-851d-c9f6a703ab69" }, { "parameters": {}, "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ 3104, 768 ], "id": "a2082638-94e3-4a91-aeac-f7849833a6a1", "name": "When clicking ‘Execute workflow’" }, { "parameters": { "method": "POST", "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $('Valores').item.json.user }}/{{ $('Valores').item.json.repo_name }}/contents/{{ $('Valores').item.json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"message\": \"{{ $json.message }}\",\n \"content\": \"{{ $json.content }}\",\n \"branch\": \"{{ $json.branch }}\"\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 4080, 880 ], "id": "e428eaaf-f678-45ac-bbcc-926f8bd574b7", "name": "Subir archivo", "retryOnFail": false, "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } } }, { "parameters": { "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $json.user }}/{{ $json.repo_name }}/contents/{{ $json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendHeaders": true, "headerParameters": { "parameters": [] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3472, 768 ], "id": "58d2c064-8982-42b0-8f1a-a10d018dff94", "name": "Obtener archivo", "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } }, "onError": "continueErrorOutput" }, { "parameters": { "method": "PUT", "url": "=https://git.digitalcompass.agency/api/v1/repos/{{ $('Valores').item.json.user }}/{{ $('Valores').item.json.repo_name }}/contents/{{ $('Valores').item.json.file_name }}.json", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"message\": \"{{ $json.message }}\",\n \"content\": \"{{ $json.content }}\",\n \"sha\": \"{{ $json.sha }}\",\n \"branch\": \"{{ $json.branch }}\"\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 4080, 672 ], "id": "f804d797-946f-4673-8291-308d47ede436", "name": "Actualizar archivo", "credentials": { "httpHeaderAuth": { "id": "R4tnNpYoEjhBYeUT", "name": "Eidan - gitea" } } }, { "parameters": { "operation": "get", "workflowId": { "__rl": true, "value": "F1iPg8hktNAebZua", "mode": "list", "cachedResultName": "GLMWay (#F1iPg8hktNAebZua)" }, "requestOptions": {} }, "type": "n8n-nodes-base.n8n", "typeVersion": 1, "position": [ 3728, 672 ], "id": "a6420476-f217-4079-b7a0-194969a2dac2", "name": "Get a workflow1", "credentials": { "n8nApi": { "id": "73Ydc9X8h5HXvFrt", "name": "Eidan - n8n account" } } }, { "parameters": { "operation": "get", "workflowId": { "__rl": true, "value": "F1iPg8hktNAebZua", "mode": "list", "cachedResultName": "GLMWay (#F1iPg8hktNAebZua)" }, "requestOptions": {} }, "type": "n8n-nodes-base.n8n", "typeVersion": 1, "position": [ 3728, 880 ], "id": "f96e2477-f9db-4d36-a162-836d05dcd8ab", "name": "Get a workflow2", "credentials": { "n8nApi": { "id": "73Ydc9X8h5HXvFrt", "name": "Eidan - n8n account" } } }, { "parameters": { "assignments": { "assignments": [ { "id": "31558805-f167-47c4-b0b4-46b8a80ca282", "name": "user", "value": "mgomez", "type": "string" }, { "id": "3519ad4c-6d66-4963-ab76-ee5517d88d67", "name": "repo_name", "value": "calendario-glm-way", "type": "string" }, { "id": "0df99f1e-1354-43b9-9d20-9f994cc82cf6", "name": "file_name", "value": "glmway-workflow", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 3296, 768 ], "id": "fa4f3a95-6fe7-41c4-9a90-f4a3f58e06a8", "name": "Valores" }, { "parameters": { "jsCode": "const sha = $('Obtener archivo').first().json.sha;\nconst data = { $json };\n\nreturn [{\n json: {\n message: \"Update \" + $('Valores').first().json.file_name + \".json\",\n content: Buffer.from(JSON.stringify(data, null, 2)).toString(\"base64\"),\n sha: sha,\n branch: \"main\"\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3904, 672 ], "id": "5d50d650-f0b6-4046-b9c1-974664b655f6", "name": "Code in JavaScript2" }, { "parameters": { "jsCode": "const sha = $json.sha; // viene del GET anterior\nconst data = { $json };\n\nconst base64 = Buffer.from(JSON.stringify(data, null, 2)).toString(\"base64\");\n\nreturn [{\n json: {\n message: \"Create \" + $('Valores').first().json.file_name + \".json\",\n content: base64,\n sha: sha,\n branch: \"main\"\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3904, 880 ], "id": "30ffb25f-3ad7-465d-9630-887828df95f6", "name": "Code in JavaScript4" }, { "parameters": { "operation": "get", "employeeId": "={{ $json.body.employees[0].id }}", "options": {} }, "type": "n8n-nodes-base.bambooHr", "typeVersion": 1, "position": [ -176, -144 ], "id": "5b4b3106-f932-4430-a11e-ebcc1740f884", "name": "Get an employee", "credentials": { "bambooHrApi": { "id": "VwYITXROyinOC4je", "name": "Eidan - BambooHR account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 16 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -336, 2144 ], "id": "7f7d71b2-6c53-49a2-92d8-e66b2d0bff54", "name": "Schedule Trigger" }, { "parameters": { "url": "=https://glm.bamboohr.com/api/v1/employees/{{ $json.id }}?fields=supervisorEmail,hireDate,supervisorEId,jobTitle", "authentication": "genericCredentialType", "genericAuthType": "httpBasicAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "application/json" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 0, -144 ], "id": "ae2aff4d-5874-4181-9801-cf51d5cc4ff3", "name": "Informacion extra del empleado", "retryOnFail": true, "waitBetweenTries": 2000, "credentials": { "httpBasicAuth": { "id": "vXrW3oJWVhNbzB07", "name": "GLM Credential" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ Object.keys($json).length }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 912, -352 ], "id": "8a2be7cc-85ad-4e44-92a7-fe3f94df703f", "name": "Hay coordinador?" }, { "parameters": { "content": "## Formato fecha\nyyyy-mm-dd\n", "height": 192, "width": 192 }, "type": "n8n-nodes-base.stickyNote", "position": [ 128, -224 ], "typeVersion": 1, "id": "8de8b400-70cb-4367-bddc-d42876f18d52", "name": "Sticky Note" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $json.isValid }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 528, -256 ], "id": "cb43a2bb-7743-4994-a7b2-209cd0934cd7", "name": "Entra hoy?" }, { "parameters": { "rule": { "interval": [ { "field": "hours" } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 352 ], "id": "20e1c800-bf0b-4484-b836-14bc7154e4e7", "name": "Schedule Trigger1" }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Get an employee').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ null }}" }, { "fieldId": "estado", "fieldValue": "inactivo" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 752, -80 ], "id": "0a800bb8-d5f1-443e-b3b1-3ca9546eb28f", "name": "Insertar a inscritos (inactivo)", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "const hireDate = $json.hireDate;\n\n// Fecha de hoy en formato YYYY-MM-DD\nconst today = new Date().toISOString().split('T')[0];\n\n// True si hireDate es hoy o anterior\nconst isValid = hireDate <= today;\n\nreturn [\n {\n json: {\n hireDate,\n today,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 176, -144 ], "id": "241cf92b-09b1-4555-af46-7b9ff49c5e37", "name": "Calcular fecha hireDate" }, { "parameters": { "content": "## Numero wsp Matos\n\n18494105855@s.whatsapp.net", "height": 192, "width": 192 }, "type": "n8n-nodes-base.stickyNote", "position": [ 784, -640 ], "typeVersion": 1, "id": "719365c8-8099-4108-a910-83b651d81181", "name": "Sticky Note1" }, { "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": "={{ \"18494105855@s.whatsapp.net\" }}" }, { "name": "mediatype", "value": "=image" }, { "name": "text", "value": "=⚠️ No hay coordinador RRHH en el país de este nuevo ingreso:\n\nNombre: {{ $('Get an employee').item.json.displayName }}\nCorreo: {{ $('Get an employee').item.json.workEmail }}\nPaís: {{ $('Get an employee').item.json.location }}\n\n#GLMWay" }, { "name": "delay", "value": "={{5000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1088, -192 ], "id": "09ce1f03-3dfb-4108-9d25-6c05ac622a6f", "name": "Alerta no hay coordinador RRHH" }, { "parameters": { "operation": "get", "employeeId": "={{ $json.empleado_id }}", "options": {} }, "type": "n8n-nodes-base.bambooHr", "typeVersion": 1, "position": [ 192, 352 ], "id": "9e00d1ce-5533-4357-977e-31a8da97f232", "name": "Get an employee1", "retryOnFail": true, "credentials": { "bambooHrApi": { "id": "VwYITXROyinOC4je", "name": "Eidan - BambooHR account" } } }, { "parameters": { "url": "=https://glm.bamboohr.com/api/v1/employees/{{ $json.id }}?fields=supervisorEmail,hireDate,supervisorEId,jobTitle", "authentication": "genericCredentialType", "genericAuthType": "httpBasicAuth", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "accept", "value": "application/json" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 352 ], "id": "06c32cb0-a8ab-42c1-ae36-fe628b1b5e2b", "name": "Informacion extra del empleado1", "retryOnFail": true, "waitBetweenTries": 2000, "credentials": { "httpBasicAuth": { "id": "vXrW3oJWVhNbzB07", "name": "GLM Credential" } } }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ -16, 352 ], "id": "36c1682f-35a1-4016-b2ac-77f7e20e3e59", "name": "Loop Over Items" }, { "parameters": { "sendTo": "={{ $('Get an employee').item.json.workEmail }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=Hola, GLMer!\n\nEste {{ $('Convertir fecha a espanol').item.json.fechaFormateada }} a las {{ $json.hora_convertida }} tenemos entrenamiento, y queremos transmitirte nuestra cultura, nuestro ADN y por qué somos diferentes al resto.\n\nTe esperamos puntual y con todas las ganas de aprender.\n\nNos vemos en el enlace!\n\n{{ $('Obtener sesiones español').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2656, -336 ], "id": "e6c3acf5-d54b-4e00-b7a9-74038d27e387", "name": "Send a message espanol", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Get an employee').item.json.workEmail }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis {{ $('Convertir fecha a ingles').item.json.fechaFormateada }} at {{ $json.hora_convertida }} we have training, and we want to share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesiones ingles').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2656, -160 ], "id": "f173c8d1-9311-405c-a7ee-164726df32f1", "name": "Send a message ingles", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "content": "## Recordatorio a nuevo ingreso 24 horas antes de la sesion\n", "height": 480, "width": 2256, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 736 ], "typeVersion": 1, "id": "ba58d863-3211-4f53-b087-eb53ba839499", "name": "Sticky Note2" }, { "parameters": { "content": "## Recordatorio a coordinador RRHH 48 y 24 horas antes de la sesion\n", "height": 496, "width": 2928, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 1280 ], "typeVersion": 1, "id": "e32bdd94-d61e-4b43-bf60-7acab8c0d3ae", "name": "Sticky Note3" }, { "parameters": { "content": "## Envio de formulario de evaluacion despues que la sesion finalize", "height": 304, "width": 2976, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 2656 ], "typeVersion": 1, "id": "6d5c0fe5-5ab1-4cdc-bfd2-197dc2144274", "name": "Sticky Note4" }, { "parameters": { "content": "## Notificacion inicial\n\nEnvia notificacion de sesion en el primer dia de trabajo del empleado", "height": 608, "width": 3424, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, -480 ], "typeVersion": 1, "id": "cd2fe5c5-9963-410b-a61a-edc36b5aaed1", "name": "Sticky Note5" }, { "parameters": { "content": "## Completar datos y enviar invitacion", "height": 544, "width": 4032, "color": 6 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 160 ], "typeVersion": 1, "id": "126bdd3f-a050-4053-aff3-e625c8bf161c", "name": "Sticky Note6" }, { "parameters": { "jsCode": "const hireDate = $json.hireDate;\n\n// Fecha de hoy en formato YYYY-MM-DD\nconst today = new Date().toISOString().split('T')[0];\n\n// True si hireDate es hoy o anterior\nconst isValid = hireDate <= today;\n\nreturn [\n {\n json: {\n hireDate,\n today,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 560, 352 ], "id": "26d7adef-3c91-410e-b92f-69841d28c039", "name": "Calcular fecha hireDate1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $json.isValid }}", "rightValue": "", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 944, 352 ], "id": "15a1892d-01e8-432c-91f1-db236317cbca", "name": "Entra hoy?1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ [\"Jamaica\", \"Trinidad and Tobago\", \"Barbados\", \"Saint Thomas\", \"St. Croix\", \"Tobago\", \"Guyana\", \"Aruba\"].includes($('Get an employee1').item.json.location) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "false", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1696, 352 ], "id": "ce9f31d4-454e-4e31-9a22-8173b3fae392", "name": "Pais?1" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ Object.keys($json).length }}", "rightValue": 0, "operator": { "type": "number", "operation": "gt" } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 1328, 256 ], "id": "30b3a4dd-6d50-405d-9c77-27febcc50aa4", "name": "Hay coordinador?1" }, { "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": "={{ \"18494105855@s.whatsapp.net\" }}" }, { "name": "mediatype", "value": "=image" }, { "name": "text", "value": "=⚠️ No hay coordinador RRHH en el país de este nuevo ingreso:\n\nNombre: {{ $('Get an employee1').item.json.displayName }}\nCorreo: {{ $('Get an employee1').item.json.workEmail }}\nPaís: {{ $('Get an employee1').item.json.location }}\n\n#GLMWay" }, { "name": "delay", "value": "={{5000}}" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1504, 384 ], "id": "67928478-7604-45a4-9ab0-851079e1470c", "name": "Alerta no hay coordinador RRHH1" }, { "parameters": { "sendTo": "={{ $('Get an employee1').item.json.workEmail }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=Hola, GLMer!\n\nEste {{ $('Convertir fecha a espanol1').item.json.fechaFormateada }} a las {{ $json.hora_convertida }} tenemos entrenamiento, y queremos transmitirte nuestra cultura, nuestro ADN y por qué somos diferentes al resto.\n\nTe esperamos puntual y con todas las ganas de aprender.\n\nNos vemos en el enlace!\n\n{{ $('Obtener sesiones español1').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 3072, 272 ], "id": "32302b24-aa4c-4f9a-afc8-ef7e86cad56b", "name": "Send a message espanol1", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Get an employee1').item.json.workEmail }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis {{ $('Convertir fecha a ingles1').item.json.fechaFormateada }} at {{ $json.hora_convertida }} we have training, and we want to share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesiones ingles1').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 3072, 448 ], "id": "db2cb6a3-1da8-472a-95eb-1a02de2a5fa4", "name": "Send a message ingles1", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ [\"Jamaica\", \"Trinidad and Tobago\", \"Barbados\", \"Saint Thomas\", \"St. Croix\", \"Tobago\", \"Guyana\", \"Aruba\"].includes($('Get an employee').item.json.location) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "false", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1328, -256 ], "id": "b183c892-8822-4bc3-a92c-4410eac41a01", "name": "Pais?" }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 3488, 352 ], "id": "98185de1-e81a-440f-8951-f98bd78c707b", "name": "Wait", "webhookId": "22a77d35-7adb-47ec-beca-0fae7615ab5b" }, { "parameters": { "content": "## Notificacion a facilitador\n\n- Manda un listado de las personas inscritas en la sesion del miercoles al facilitador.\n- Si no hay personas inscritas envia un alerta al facilitador.", "height": 768, "width": 2208, "color": 3 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 1824 ], "typeVersion": 1, "id": "79ccf49e-4434-4b72-8147-ad27b9d994a2", "name": "Sticky Note8" }, { "parameters": { "sendTo": "={{ $('Loop Over Items1').item.json.email }}", "subject": "Entrenamiento #TheGLMWay", "emailType": "text", "message": "=¡Hola, GLMer!\n\nTe recordamos que la sesión de capacitación será el {{ $('Convertir fecha a espanol2').item.json.fechaFormateada }} a las {{ $json.hora_convertida }}. Queremos compartir nuestra cultura, nuestro ADN y aquello que nos hace diferentes al resto.\n\nContamos con tu puntualidad y tus ganas de aprender.\n\n¡Nos vemos en el enlace!\n\n{{ $('Obtener sesion').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1344, 752 ], "id": "10b2cb4e-274d-4913-9345-2c024c071f4c", "name": "Send a message espanol2", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $('Loop Over Items1').item.json.email }}", "subject": "#TheGLMWay Training", "emailType": "text", "message": "=Hello, GLMer!\n\nThis is a reminder about your training session on {{ $('Convertir fecha a ingles2').item.json.fechaFormateada }} at {{ $json.hora_convertida }} where we’ll share our culture, our DNA, and what makes us different from the rest.\n\nWe expect you to be punctual and eager to learn.\n\nSee you at the link!\n\n{{ $('Obtener sesion').item.json.enlace_reunion }}", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 1344, 960 ], "id": "1dc76989-8c58-4ffe-9e1c-5113a59d346c", "name": "Send a message ingles2", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 2, 3 ], "triggerAtHour": 17 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 928 ], "id": "60708d5c-0cd7-45fc-bb67-ed050c1f8022", "name": "Schedule Trigger2" }, { "parameters": { "operation": "get", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "estado", "keyValue": "inactivo" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 352 ], "id": "93a65a61-59a9-4903-8a35-dbf66a0ef468", "name": "Obtener inactivos", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.splitInBatches", "typeVersion": 3, "position": [ 0, 928 ], "id": "9e8fd238-541e-455b-8ae5-6a3097eb38a0", "name": "Loop Over Items1" }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 1728, 1088 ], "id": "ee5bb9bc-b8cb-493f-8463-ae0a24cf1f0d", "name": "Wait1", "webhookId": "09d53dc8-c92a-43d2-a47f-477c0d1317af" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ !['Jamaica', 'Trinidad and Tobago', 'Barbados', 'Saint Thomas', 'St. Croix', 'Tobago', 'Guyana', 'Aruba'].includes($('Obtener notificados').item.json.pais) }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 752, 832 ], "id": "4d94c907-8ab1-4213-be20-9e24173cf0a3", "name": "Pais?2" }, { "parameters": { "assignments": { "assignments": [ { "id": "1e6f83ce-19e7-4dd9-ba34-a11836a6181e", "name": "idioma", "value": "ES", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1552, -336 ], "id": "e8a65f36-8e8e-4135-b7a2-a7ef4617de2f", "name": "Crear variable idioma ES" }, { "parameters": { "assignments": { "assignments": [ { "id": "b0610214-1357-4e55-be5f-75c159d3b717", "name": "idioma", "value": "EN", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1552, -160 ], "id": "971ae719-5692-4f87-9a57-2287ee44783d", "name": "Crear variable idioma EN" }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1744, -336 ], "id": "cb9e8a10-a1e7-40c7-8447-2379b0191a8f", "name": "Obtener sesiones español", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1744, -160 ], "id": "5ca790ee-4944-4868-98af-89837ac39422", "name": "Obtener sesiones ingles", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1936, -336 ], "id": "c2db5e62-7741-4ff2-ad31-71c108dd7386", "name": "Calcular sesion mas cercana" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1936, -160 ], "id": "bde8fba9-0d6c-4299-8971-dcd8e0e740b4", "name": "Calcular sesion mas cercana1" }, { "parameters": { "assignments": { "assignments": [ { "id": "1e6f83ce-19e7-4dd9-ba34-a11836a6181e", "name": "idioma", "value": "ES", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1952, 272 ], "id": "430a2b66-f0f3-4032-bca1-29b01bd8c577", "name": "Crear variable idioma ES1" }, { "parameters": { "assignments": { "assignments": [ { "id": "b0610214-1357-4e55-be5f-75c159d3b717", "name": "idioma", "value": "EN", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1952, 448 ], "id": "9d53a7e1-6dab-494b-8064-6c3063f5596f", "name": "Crear variable idioma EN1" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?1').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2336, 272 ], "id": "ee31fd24-d703-44b3-b65b-75234564d29f", "name": "Calcular sesion mas cercana2" }, { "parameters": { "jsCode": "const hireDate = new Date($('Entra hoy?1').first().json.hireDate);\nconst today = new Date();\nconst sessions = $input.all();\n\n// Eliminar horas para comparar solo fechas\nhireDate.setHours(0, 0, 0, 0);\ntoday.setHours(0, 0, 0, 0);\n\n// La búsqueda comienza desde la fecha más reciente\nconst searchDate = hireDate > today ? hireDate : today;\n\n// Helper para parsear \"14 January\" → Date\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n\n const [day, month] = dateStr.split(' ');\n const currentYear = today.getFullYear();\n\n const date = new Date(`${month} ${day}, ${currentYear}`);\n date.setHours(0, 0, 0, 0);\n\n return date;\n}\n\nconst validSessions = sessions.filter(item => {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n return sessionDate && sessionDate >= searchDate;\n});\n\nvalidSessions.sort((a, b) =>\n parseSessionDate(a.json.fecha_sesion) -\n parseSessionDate(b.json.fecha_sesion)\n);\n\nconst nearestSession = validSessions[0];\n\nreturn [\n {\n json: {\n hireDate: hireDate.toISOString().split('T')[0],\n today: today.toISOString().split('T')[0],\n searchDate: searchDate.toISOString().split('T')[0],\n foundSession: !!nearestSession,\n session: nearestSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2336, 448 ], "id": "24f2e53d-9280-445b-b37e-776b41ca53e2", "name": "Calcular sesion mas cercana3" }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" }, { "fieldId": "coordinador_rrhh", "fieldValue": "={{ $('Obtener coordinador3').item.json.nombre }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2096, -336 ], "id": "dcdef9fc-9c61-45dd-9604-56037eac4c31", "name": "Guardar datos del empleado y sesion asignada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "tableId": "inscritos_glmway", "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee').item.json.jobTitle }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee').item.json.location }}" }, { "fieldId": "coordinador_rrhh", "fieldValue": "={{ $('Obtener coordinador3').item.json.nombre }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2096, -160 ], "id": "7530270a-b32e-419e-8fc5-b29fa07dda39", "name": "Guardar datos del empleado y sesion asignada1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2144, 272 ], "id": "f034ee45-742b-4f18-9003-333a4c087cf7", "name": "Obtener sesiones español1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "idioma", "keyValue": "={{ $json.idioma }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2144, 448 ], "id": "2c35fe0e-1f32-4263-9c02-c392cb77e0e5", "name": "Obtener sesiones ingles1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "amount": 2 }, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 1136, 496 ], "id": "960e74ae-583b-4802-ab72-3b402c095d9b", "name": "Wait2", "webhookId": "1211d7da-55b9-4a73-837d-55934076a799" }, { "parameters": { "operation": "get", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "estado", "keyValue": "notificado" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 928 ], "id": "34aa0bc5-0feb-46e3-871b-27a1cc418675", "name": "Obtener notificados", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.isValid }}", "rightValue": "Jamaica", "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 416, 928 ], "id": "107b41cb-06d5-4e7e-863b-dace19c8d1e9", "name": "Falta 24h para el evento?" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Loop Over Items1').item.json.empleado_id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "estado", "fieldValue": "recordado" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1568, 880 ], "id": "ddf0a273-d3bc-44cc-888b-d789ce72ff77", "name": "Actualizar estado a recordado", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 2 ], "triggerAtHour": 16 }, { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 16 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -352, 1504 ], "id": "6951af7d-5098-4156-81bd-8f67034fcf70", "name": "Schedule Trigger3" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.pais }}", "rightValue": "Jamaica", "operator": { "type": "string", "operation": "equals" } }, { "id": "32931394-f4ea-4055-b866-906a81988173", "leftValue": "={{ $json.pais }}", "rightValue": "Trinidad and Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "ea2a8466-96c6-460f-b08f-d23c06b2d18c", "leftValue": "={{ $json.pais }}", "rightValue": "Barbados", "operator": { "type": "string", "operation": "equals" } }, { "id": "28e49217-0c1a-4462-9642-676e54926d3e", "leftValue": "={{ $json.pais }}", "rightValue": "Saint Thomas", "operator": { "type": "string", "operation": "equals" } }, { "id": "c6a6aea5-48f4-44dc-92ca-a9f9de9cacf9", "leftValue": "={{ $json.pais }}", "rightValue": "St. Croix", "operator": { "type": "string", "operation": "equals" } }, { "id": "e6f52339-ea7c-462f-bdc2-8b7353160e4c", "leftValue": "={{ $json.pais }}", "rightValue": "Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "b308c2b6-53b4-4d49-b540-cdc03e36528b", "leftValue": "={{ $json.pais }}", "rightValue": "Guyana", "operator": { "type": "string", "operation": "equals" } }, { "id": "35a50a33-a2b5-4116-9336-11300357569e", "leftValue": "={{ $json.pais }}", "rightValue": "Aruba", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 1520, 1488 ], "id": "13ee807a-f1cd-48ef-921b-7b5c260ba116", "name": "Pais?3" }, { "parameters": { "jsCode": "// Helper para parsear \"14 December\" → Date (año actual)\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\n// Formatear fecha como \"26 June\"\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\nconst fecha_sesion = $input.first().json.fecha_sesion_inscrito;\n\n// Fecha de hoy normalizada a medianoche\nconst hoy = new Date();\nhoy.setHours(0, 0, 0, 0);\n\nconst sesion = parseSessionDate(fecha_sesion);\nsesion.setHours(0, 0, 0, 0);\n\n// Diferencia en días\nconst diferenciaDias = Math.floor(\n (sesion - hoy) / (1000 * 60 * 60 * 24)\n);\n\n// True si es hoy (0 días) o mañana (1 día)\nconst isValid = diferenciaDias >= 0 && diferenciaDias <= 1;\n\nreturn [\n {\n json: {\n fecha_sesion,\n fecha_hoy: formatDate(hoy),\n diferenciaDias,\n isValid\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 208, 928 ], "id": "bbd0558c-3b3a-462b-957c-83b1975e5413", "name": "Calcular falta 24h o es el mismo dia" }, { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "expression": "0 0 0 1 1 *" } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 3440, -352 ], "id": "ca136518-b776-45ba-b1a2-ad5327dd4cca", "name": "Schedule Trigger4" }, { "parameters": { "operation": "appendOrUpdate", "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "columns": { "mappingMode": "defineBelow", "value": { "Fecha": "={{ $json.start }}" }, "matchingColumns": [ "Fecha" ], "schema": [ { "id": "Fecha", "displayName": "Fecha", "required": false, "defaultMatch": false, "display": true, "type": "string", "canBeUsedToMatch": true, "removed": false } ], "attemptToConvertTypes": false, "convertFieldsToString": false }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 4336, -352 ], "id": "7c321f7d-bce9-447c-b94c-35f6967a48e3", "name": "Insertar fechas", "alwaysOutputData": false, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": {}, "type": "n8n-nodes-base.wait", "typeVersion": 1.1, "position": [ 4160, -352 ], "id": "27531838-5dc7-4169-a08a-f4da93899580", "name": "Wait4", "webhookId": "85cfdcd9-384b-47e8-9d7d-4e079f0a4d97" }, { "parameters": { "operation": "clear", "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "clear": "specificRange", "range": "A2:D80" }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 3984, -352 ], "id": "bd8cb535-6aa3-46df-9ca0-6efc0555f2e4", "name": "Borrar fechas", "alwaysOutputData": false, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "content": "## Borrar y guardar las nuevas fechas de las sesiones del nuevo año en el sheets\n\nEste trigger se activa todos los años el 1 de enero", "height": 288, "width": 1072 }, "type": "n8n-nodes-base.stickyNote", "position": [ 3408, -480 ], "typeVersion": 1, "id": "ddcb9db1-2590-4364-aeeb-db79c35ea604", "name": "Sticky Note10" }, { "parameters": { "sendTo": "={{ $json.email }}", "subject": "Evaluación #TheGLMWay", "message": "=\n\n\n \n \n Gracias por tu participación #TheGLMWay\n\n\n
\n\n\n \n \n \n \n
\n

Evaluación #TheGLMWay

\n
\n \"GLM\n
\n \n
\n

\n Hola {{ $json.primerNombre }},\n

\n

\n ¡Gracias por participar en la sesión #TheGLMWay!

\n

\n Para seguir mejorando estos espacios, nos encantaría conocer tu opinión sobre lo visto en la sesión. Responder la evaluación te tomará menos de 5 minutos.\n

\n \n
\n
\n \"Google\n

Evaluación #TheGLMWay

\n
\n \n \n Completar evaluación\n \n
\n
\n
\n\n", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2400, 2848 ], "id": "3c22bc65-799f-4432-86fe-10ae92e036de", "name": "Send a message espanol4", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "sendTo": "={{ $json.email }}", "subject": "#TheGLMWay Quiz", "message": "=\n\n\n \n \n Thank you for participating #TheGLMWay\n\n\n
\n\n\n \n \n \n \n
\n

#TheGLMWay Quiz

\n
\n \"GLM\n
\n \n
\n

\n Hi {{ $json.primerNombre }},\n

\n

\n Thank you for taking part in the #TheGLMWay session!

\n

\n To keep improving these sessions, we'd love to hear your thoughts on what was covered. Completing the quiz will take less than 5 minutes.\n

\n \n
\n
\n \"Google\n

#TheGLMWay Quiz

\n
\n \n \n Complete quiz\n \n
\n
\n
\n\n", "options": { "appendAttribution": false } }, "type": "n8n-nodes-base.gmail", "typeVersion": 2.2, "position": [ 2400, 2672 ], "id": "4dfc0135-6886-4d33-9b2a-a26efbe72832", "name": "Send a message ingles4", "webhookId": "a6043707-89d1-4c99-8de2-e60d9aaf7ed2", "credentials": { "gmailOAuth2": { "id": "QWNicjw1khRm5BVI", "name": "Eidan - Gmail account" } } }, { "parameters": { "operation": "getAll", "calendar": { "__rl": true, "value": "ethen@gomezleemarketing.com", "mode": "list", "cachedResultName": "ethen@gomezleemarketing.com" }, "returnAll": true, "timeMin": "={{ $now.startOf('year') }}", "timeMax": "={{ $now.endOf('year') }}", "options": { "orderBy": "startTime", "query": "#TheGLMWay" } }, "type": "n8n-nodes-base.googleCalendar", "typeVersion": 1.3, "position": [ 3632, -352 ], "id": "b2b03ce6-6010-4e4f-be7a-d9040286e295", "name": "Obtener entrenamientos ingles y espanol", "credentials": { "googleCalendarOAuth2Api": { "id": "yEmGG4av5RxOK7wu", "name": "Eidan - Google Calendar account" } } }, { "parameters": { "jsCode": "const months = [\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];\n\nfunction formatDate(dateTimeStr) {\n if (!dateTimeStr) return null;\n const datePart = dateTimeStr.split('T')[0]; // \"2026-01-07\"\n const [year, month, day] = datePart.split('-');\n return `${parseInt(day, 10)} ${months[parseInt(month, 10) - 1]}`;\n}\n\nconst output = [];\n\nfor (const item of $input.all()) {\n const event = item.json;\n output.push({\n json: {\n id: event.id,\n summary: event.summary,\n start: `'${formatDate(event.start?.dateTime || event.start?.date)}`,\n end: formatDate(event.end?.dateTime || event.end?.date)\n }\n });\n}\n\nreturn output;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 3808, -352 ], "id": "73c39af9-bc01-4d97-81ee-846aff70b3a6", "name": "Formatear fecha" }, { "parameters": { "rule": { "interval": [ { "triggerAtHour": 11 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 3440, -48 ], "id": "55a755d8-8b74-440f-93c6-8a1ecba4c666", "name": "Schedule Trigger5" }, { "parameters": { "content": "## Añadir/actualizar coordinadores RRHH\nEste trigger se activa todos los dias a las 11am", "height": 288, "width": 1072 }, "type": "n8n-nodes-base.stickyNote", "position": [ 3408, -160 ], "typeVersion": 1, "id": "3fd1379f-78d1-40a8-b24f-f8f086fda80a", "name": "Sticky Note12" }, { "parameters": { "operation": "getAll", "calendar": { "__rl": true, "value": "ethen@gomezleemarketing.com", "mode": "list", "cachedResultName": "ethen@gomezleemarketing.com" }, "returnAll": true, "timeMin": "={{ $now.startOf('year') }}", "timeMax": "={{ $now.endOf('year') }}", "options": { "orderBy": "startTime", "query": "#TheGLMWay" } }, "type": "n8n-nodes-base.googleCalendar", "typeVersion": 1.3, "position": [ 4784, -208 ], "id": "3c32f96e-cd34-4be4-8c24-b4be7a8f29d9", "name": "Obtener entrenamientos ingles y espanol1", "credentials": { "googleCalendarOAuth2Api": { "id": "yEmGG4av5RxOK7wu", "name": "Eidan - Google Calendar account" } } }, { "parameters": { "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": 169172567, "mode": "list", "cachedResultName": "Coordinadores RRHH", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=169172567" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 3616, -48 ], "id": "73089147-ba1f-4fb4-ac17-d5670b263fd8", "name": "Obtener coordinadores", "alwaysOutputData": false, "retryOnFail": true, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_coordinadores_rrhh_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ \"input\": $json.input }) }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3952, -48 ], "id": "231f396b-855a-4c50-8d6d-096018e6d2ac", "name": "Insertar/actualizar coordinadores a la bd" }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "input", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 3776, -48 ], "id": "e51bd2d5-22b5-46cf-b346-c1ba16bb5c34", "name": "Aggregate" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/sync_sesiones_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ \"input\": $json.input }) }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 5584, -304 ], "id": "3f4a0807-5f29-49cb-a851-41100e04f5bf", "name": "Insertar fechas1" }, { "parameters": { "aggregate": "aggregateAllItemData", "destinationFieldName": "input", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 5440, -304 ], "id": "3ecbb0c7-f5f5-4644-9f42-8be9502e814d", "name": "Aggregate1" }, { "parameters": { "mode": "raw", "jsonOutput": "={\n \"meet_id\": \"{{ $json.id }}\",\n \"titulo\": \"{{ $json.titulo }}\",\n \"fecha_sesion\": \"{{ $json.fecha }}\",\n \"hora_inicio\": \"{{ $json.hora_inicio }}\",\n \"hora_fin\": \"{{ $json.hora_fin }}\",\n \"instructor\": \"{{ $json.Espanol || $json.English || null }}\",\n \"correo_instructor\": \"{{ $json.Correo || null }}\",\n \"enlace_reunion\": \"{{ $json.url }}\",\n \"idioma\": \"{{ $json.idioma }}\"\n}", "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 5296, -304 ], "id": "a099259d-36e3-48b6-aa77-d8132f33f85e", "name": "Edit Fields" }, { "parameters": { "mode": "combine", "advanced": true, "mergeByFields": { "values": [ { "field1": "Fecha", "field2": "fecha" } ] }, "options": {} }, "type": "n8n-nodes-base.merge", "typeVersion": 3.2, "position": [ 5152, -304 ], "id": "456bcbe4-cc98-48fc-bcd2-40f8961934ae", "name": "Unir datos" }, { "parameters": { "content": "## Actualizar instructores y fechas de las sesiones en supabase\n\nEste trigger se activa todos los dias a las 3pm", "height": 416, "width": 1152 }, "type": "n8n-nodes-base.stickyNote", "position": [ 4576, -480 ], "typeVersion": 1, "id": "b1eff313-9251-48db-a6f3-9f0e81c644a3", "name": "Sticky Note13" }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 15 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ 4624, -288 ], "id": "6ef829bf-1d52-4093-bcc5-45d922393611", "name": "Schedule Trigger6" }, { "parameters": { "documentId": { "__rl": true, "value": "1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg", "mode": "list", "cachedResultName": "Calendario #TheGLMWay", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit?usp=drivesdk" }, "sheetName": { "__rl": true, "value": "gid=0", "mode": "list", "cachedResultName": "Calendario", "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg/edit#gid=0" }, "options": {} }, "type": "n8n-nodes-base.googleSheets", "typeVersion": 4.7, "position": [ 4784, -384 ], "id": "f1bf8c51-43cf-41d4-93c4-1a1d0a0dac7a", "name": "Obtener fechas e instructores", "alwaysOutputData": false, "retryOnFail": true, "credentials": { "googleSheetsOAuth2Api": { "id": "8Pp0ek3NPsEkyXfY", "name": "Eidan - Google Sheets account" } } }, { "parameters": { "jsCode": "const months = [\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];\n\nfunction formatearFecha(dateTimeStr) {\n if (!dateTimeStr) return null;\n const datePart = dateTimeStr.split('T')[0];\n const [year, month, day] = datePart.split('-');\n return `${parseInt(day, 10)} ${months[parseInt(month, 10) - 1]}`;\n}\n\nfunction detectarIdioma(summary) {\n if (!summary) return null;\n if (summary.includes(\"#TheGLMWay Training\")) return \"EN\";\n if (summary.includes(\"Entrenamiento #TheGLMWay\")) return \"ES\";\n return null;\n}\n\nfunction formatearHora(dateTimeStr) {\n if (!dateTimeStr) return null;\n const timePart = dateTimeStr.split('T')[1];\n if (!timePart) return null;\n return timePart.substring(0, 5);\n}\n\nconst output = [];\n\nfor (const item of $input.all()) {\n const event = item.json;\n\n const startRaw = event.start?.dateTime || event.start?.date;\n const endRaw = event.end?.dateTime || event.end?.date;\n const url = event.conferenceData?.entryPoints?.[0]?.uri || null;\n const idioma = detectarIdioma(event.summary);\n\n // Ignorar eventos vacíos o sin datos esenciales\n if (!event.summary || !startRaw) {\n console.log(\"Evento ignorado (vacío):\", JSON.stringify(event));\n continue;\n }\n\n output.push({\n json: {\n id: event.id,\n titulo: event.summary,\n idioma: idioma,\n fecha: formatearFecha(startRaw),\n hora_inicio: formatearHora(startRaw),\n hora_fin: formatearHora(endRaw),\n url: url,\n descripcion: event.description || null\n }\n });\n}\n\nconsole.log(`Sesiones procesadas: ${output.length}`);\nreturn output;\n\n// Agrega esto antes del return output\nconst resumen = output.map(i => ({\n meet_id: i.json.meet_id,\n titulo: i.json.titulo,\n fecha_sesion: i.json.fecha_sesion,\n hora_inicio: i.json.hora_inicio,\n hora_fin: i.json.hora_fin,\n enlace_reunion: i.json.enlace_reunion,\n idioma: i.json.idioma\n}));\nconsole.log(JSON.stringify(resumen));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 4960, -208 ], "id": "8f80d9ca-1e4b-4753-b482-df7b0fd24f61", "name": "Formatear fecha y detectar idioma" }, { "parameters": { "jsCode": "const today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst sessions = $input.all();\n\n// Helper para parsear \"14 January\" → Date (año actual)\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\n// Formatear fecha como \"26 June\"\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\n// Iterar hasta encontrar la sesión que hace match con hoy\nlet matchedSession = null;\n\nfor (const item of sessions) {\n const sessionDate = parseSessionDate(item.json.fecha_sesion);\n if (!sessionDate) continue;\n\n sessionDate.setHours(0, 0, 0, 0);\n\n if (sessionDate.getTime() === today.getTime()) {\n matchedSession = item;\n break;\n }\n}\n\nreturn [\n {\n json: {\n today: formatDate(today),\n foundSession: !!matchedSession,\n session: matchedSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 0, 2144 ], "id": "0db9e6a4-2e5e-4513-97fd-71d22aa90822", "name": "Calcular sesion mas cercana4" }, { "parameters": { "content": "## Añadir instructor al particpante", "height": 240, "width": 384, "color": 5 }, "type": "n8n-nodes-base.stickyNote", "position": [ 1296, 2912 ], "typeVersion": 1, "id": "a9266141-49ab-41f7-b8ab-dc45e746ed1c", "name": "Sticky Note14" }, { "parameters": { "operation": "getAll", "tableId": "sesiones_glmway", "returnAll": true, "filters": { "conditions": [] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -192, 1504 ], "id": "a4fc1575-5326-467f-8b05-f8c9569cdca1", "name": "Obtener sesiones", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "getAll", "tableId": "coordinadores_rrhh_glmway", "returnAll": true, "filters": { "conditions": [ { "keyName": "estado", "condition": "eq", "keyValue": "=no_notificado" }, { "keyName": "pais", "condition": "eq", "keyValue": "={{ $json.sesion.participantes }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 464, 1488 ], "id": "0457dbf8-9c04-4f2d-9928-4f770eb51cc0", "name": "Obtener coordinadores1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "19e418dd-962b-4fe6-82db-19247f0e8165", "leftValue": "={{ $json.sesion.participantes }}", "rightValue": "", "operator": { "type": "object", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 208, 1504 ], "id": "334a5703-db8a-4a88-b528-8468ee61ddbc", "name": "Hay inscritos en la sesion?" }, { "parameters": { "jsCode": "// 1. Obtener la sesión del nodo anterior\nconst datosNodoAnterior = $(\"Calcular falta 48h o 24h1\").first().json;\nconst sesion = datosNodoAnterior.sesion;\nconst participantesPorPais = sesion?.participantes || {};\n\n// 2. Obtener todos los coordinadores\nconst coordinadores = $(\"Obtener coordinadores1\").all().map(i => i.json);\n\nconst resultado = [];\n\n// Función para quitar acentos y dejar en minúsculas (evita fallos de coincidencia)\nconst limpiarTexto = (texto) => \n texto ? texto.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\").trim() : \"\";\n\n// 3. Recorrer los países que tienen participantes en la sesión\nfor (const [paisParticipante] of Object.entries(participantesPorPais)) {\n\n // Buscar el coordinador cuyo país coincida limpiando acentos\n const coordinadorMatch = coordinadores.find(c => \n limpiarTexto(c.pais) === limpiarTexto(paisParticipante)\n );\n\n resultado.push({\n json: {\n pais: paisParticipante,\n coordinador: coordinadorMatch \n ? {\n nombre: coordinadorMatch.nombre,\n correo: coordinadorMatch.correo,\n pais_coordinador: coordinadorMatch.pais\n } \n : null,\n }\n });\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 656, 1488 ], "id": "3073d739-a2c7-4ba1-81bc-aeae266ad3ff", "name": "Matchear coordinador y pais inscrito" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "df25aa3e-d48f-4e52-ae1f-47678e954d52", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.participantes }}", "rightValue": "EN", "operator": { "type": "object", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 864, 2144 ], "id": "d1472787-4c2f-4e1d-8673-5c2368d469ab", "name": "Hay inscritos?" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee').item.json.department }}\",\n \"division\": \"{{ $('Get an employee').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2848, -336 ], "id": "4ab5f973-c2e1-410e-9212-8ed3b9d372e3", "name": "Registrar empleado a la sesion" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana1').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee').item.json.department }}\",\n \"division\": \"{{ $('Get an employee').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2848, -160 ], "id": "5e69165f-16a2-4f7a-ad48-d24c70f3c88b", "name": "Registrar empleado a la sesion1" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana2').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee1').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee1').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee1').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee1').item.json.department }}\",\n \"division\": \"{{ $('Get an employee1').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3280, 272 ], "id": "f3df197d-b557-45d7-94bb-76f3c300ae61", "name": "Registrar empleado a la sesion2" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/insertar_participantes_sesion_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"p_sesion_id\": \"{{ $('Calcular sesion mas cercana3').item.json.session.id }}\",\n \"p_pais\": \"{{ $('Get an employee1').item.json.location }}\",\n \"p_empleados\": [\n {\n \"nombre\": \"{{ $('Get an employee1').item.json.displayName }}\",\n \"correo\": \"{{ $('Get an employee1').item.json.workEmail }}\",\n \"departamento\": \"{{ $('Get an employee1').item.json.department }}\",\n \"division\": \"{{ $('Get an employee1').item.json.division }}\"\n }\n ]\n}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 3280, 448 ], "id": "23ac8709-b0ac-4bb6-911a-1e7641be075d", "name": "Registrar empleado a la sesion3" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Calcular sesion mas cercana').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2272, -336 ], "id": "ad0bb609-e224-4956-bf20-0d624f4ef3ae", "name": "Convertir fecha a espanol" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nconst fecha = $('Calcular sesion mas cercana1').first().json.session.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\nconst partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\nconst dia = partes[0];\nconst mes = partes[1];\nconst diaConSufijo = getOrdinalSuffix(dia);\n\nconst fechaFormateada = `${mes} ${diaConSufijo}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2272, -160 ], "id": "a1ad0e55-59e3-405e-b75d-d092112e9151", "name": "Convertir fecha a ingles" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Calcular sesion mas cercana2').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2688, 272 ], "id": "0d7870a9-0d82-49fe-96de-05c20164cffa", "name": "Convertir fecha a espanol1" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nfor (const item of $input.all()) {\n const fecha = $('Calcular sesion mas cercana3').first().json.session.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\n const partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\n const dia = partes[0];\n const mes = partes[1];\n const diaConSufijo = getOrdinalSuffix(dia);\n\n item.json.fechaFormateada = `${mes} ${diaConSufijo}`;\n}\n\nreturn $input.all();" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2688, 448 ], "id": "4abc2638-3ae3-4aba-b45f-0b60e73e3267", "name": "Convertir fecha a ingles1" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Guardar datos del empleado y sesion asignada').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2464, -336 ], "id": "740373c9-0145-41f4-a4b6-9dbb84ffbdaa", "name": "Cambiar zona horaria" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana1')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Guardar datos del empleado y sesion asignada1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2464, -160 ], "id": "77da2dc7-546b-4ab7-a7c7-fa621196b2d0", "name": "Cambiar zona horaria1" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana2')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Actualizar datos del empleado y sesion asignada').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2880, 272 ], "id": "bbd8c7de-64eb-4262-a77b-b7307ab9c0c6", "name": "Cambiar zona horaria2" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = $('Calcular sesion mas cercana3')\n .first()\n .json\n .session\n .hora_inicio;\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Actualizar datos del empleado y sesion asignada1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2880, 448 ], "id": "677acc91-b856-482e-aa2c-9b329221918a", "name": "Cambiar zona horaria3" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = \"19:00\";\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Loop Over Items1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1152, 752 ], "id": "67785f93-1b98-43f4-a72b-c94072ca22e6", "name": "Cambiar zona horaria4" }, { "parameters": { "jsCode": "const TIMEZONES = {\n \"Argentina\": \"America/Argentina/Buenos_Aires\",\n \"Bolivia\": \"America/La_Paz\",\n \"Brasil\": \"America/Sao_Paulo\",\n \"Chile\": \"America/Santiago\",\n \"Colombia\": \"America/Bogota\",\n \"Costa Rica\": \"America/Costa_Rica\",\n \"Cuba\": \"America/Havana\",\n \"Ecuador\": \"America/Guayaquil\",\n \"El Salvador\": \"America/El_Salvador\",\n \"Guatemala\": \"America/Guatemala\",\n \"Honduras\": \"America/Tegucigalpa\",\n \"Mexico\": \"America/Mexico_City\",\n \"Nicaragua\": \"America/Managua\",\n \"Panama\": \"America/Panama\",\n \"Paraguay\": \"America/Asuncion\",\n \"Peru\": \"America/Lima\",\n \"Puerto Rico\": \"America/Puerto_Rico\",\n \"Republica Dominicana\": \"America/Santo_Domingo\",\n \"Uruguay\": \"America/Montevideo\",\n \"Venezuela\": \"America/Caracas\",\n \"Jamaica\": \"America/Jamaica\",\n \"Trinidad and Tobago\": \"America/Port_of_Spain\",\n \"Guyana\": \"America/Guyana\",\n \"Surinam\": \"America/Paramaribo\",\n \"Belice\": \"America/Belize\"\n};\n\n// ==============================\n// FUNCIONES\n// ==============================\n\nfunction normalizarPais(texto) {\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .trim()\n .toLowerCase();\n}\n\nfunction obtenerOffsetMinutos(fecha, timeZone) {\n const dtf = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n hour12: false,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\"\n });\n\n const partes = dtf.formatToParts(fecha).reduce((acc, p) => {\n acc[p.type] = p.value;\n return acc;\n }, {});\n\n const utcEquivalente = Date.UTC(\n Number(partes.year),\n Number(partes.month) - 1,\n Number(partes.day),\n Number(partes.hour),\n Number(partes.minute),\n Number(partes.second)\n );\n\n return (utcEquivalente - fecha.getTime()) / 60000;\n}\n\nfunction obtenerUTCDesdeHoraLocal(horaTexto, timeZone) {\n const [hora, minuto] = horaTexto.split(\":\").map(Number);\n\n const ahora = new Date();\n\n const y = ahora.getUTCFullYear();\n const m = ahora.getUTCMonth();\n const d = ahora.getUTCDate();\n\n let fechaUTC = new Date(Date.UTC(y, m, d, hora, minuto, 0));\n\n const offset = obtenerOffsetMinutos(fechaUTC, timeZone);\n\n fechaUTC = new Date(fechaUTC.getTime() - offset * 60000);\n\n return fechaUTC;\n}\n\nfunction formatearHora(fechaUTC, timeZone) {\n return new Intl.DateTimeFormat(\"es-DO\", {\n timeZone,\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false\n }).format(fechaUTC);\n}\n\nfunction convertirHoraDesdeSantoDomingo(horaTexto) {\n\n const fechaUTC = obtenerUTCDesdeHoraLocal(\n horaTexto,\n TIMEZONES[\"Republica Dominicana\"]\n );\n\n const resultado = {};\n\n for (const [pais, tz] of Object.entries(TIMEZONES)) {\n resultado[pais] = formatearHora(fechaUTC, tz);\n }\n\n return resultado;\n}\n\n// ==============================\n// EJECUCIÓN\n// ==============================\n\nconst horaEntrada = \"19:00\";\n\nif (!horaEntrada || !/^\\d{1,2}:\\d{2}$/.test(horaEntrada)) {\n throw new Error(\n `Formato de hora inválido: \"${horaEntrada}\". Usa HH:mm, por ejemplo 19:00`\n );\n}\n\nconst conversiones = convertirHoraDesdeSantoDomingo(horaEntrada);\n\nreturn items.map(item => {\n\n const paisEntrada = $('Loop Over Items1').first().json.pais;\n\n if (!paisEntrada) {\n throw new Error('Cada item debe contener el campo \"pais\".');\n }\n\n // Buscar el país ignorando mayúsculas y acentos\n const paisEncontrado = Object.keys(TIMEZONES).find(\n pais => normalizarPais(pais) === normalizarPais(paisEntrada)\n );\n\n if (!paisEncontrado) {\n throw new Error(\n `País no reconocido: \"${paisEntrada}\". Países válidos: ${Object.keys(TIMEZONES).join(\", \")}`\n );\n }\n\n return {\n json: {\n hora_base: horaEntrada,\n pais_base: \"Republica Dominicana\",\n hora_convertida: conversiones[paisEncontrado],\n conversiones\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1152, 960 ], "id": "b574514b-817a-4798-a44b-2eae1077e118", "name": "Cambiar zona horaria5" }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion", "keyValue": "={{ $json.fecha_sesion }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 608, 832 ], "id": "45d7c217-bfee-4ae8-97b1-b158ee7e3548", "name": "Obtener sesion", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "getAll", "tableId": "sesiones_glmway", "returnAll": true, "filters": { "conditions": [] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ -176, 2144 ], "id": "d34e225b-25bb-4a0a-845c-b9e274529000", "name": "Obtener sesion1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $('Get an employee').item.json.workEmail }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } }, { "id": "ec0276ab-208e-409b-8101-d06e535f541c", "leftValue": "={{ $('Get an employee').item.json.location }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 352, -144 ], "id": "a9fff247-d1b0-4314-ba8d-e7401086b771", "name": "Tiene correo y pais?" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "d7d68505-8c34-44cd-b771-56bef28ada41", "leftValue": "={{ $('Get an employee1').item.json.workEmail }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } }, { "id": "a245c081-ef08-4ba2-8164-2d2c35bd1e17", "leftValue": "={{ $('Get an employee1').item.json.location }}", "rightValue": "", "operator": { "type": "string", "operation": "notEmpty", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 752, 352 ], "id": "a2a81e91-f617-490a-b1ce-5737944fa23b", "name": "Tiene correo y pais?1" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Get an employee1').item.json.id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee1').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee1').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee1').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee1').item.json.location }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee1').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee1').item.json.jobTitle }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2496, 272 ], "id": "16d364da-e6fc-4943-bd64-f83ccab66b9f", "name": "Actualizar datos del empleado y sesion asignada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Get an employee1').item.json.id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "empleado_id", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.id }}" }, { "fieldId": "nombre", "fieldValue": "={{ $('Get an employee1').item.json.displayName }}" }, { "fieldId": "email", "fieldValue": "={{ $('Get an employee1').item.json.workEmail }}" }, { "fieldId": "departamento", "fieldValue": "={{ $('Get an employee1').item.json.department }}" }, { "fieldId": "fecha_ingreso", "fieldValue": "={{ $('Informacion extra del empleado1').item.json.hireDate }}" }, { "fieldId": "fecha_sesion_inscrito", "fieldValue": "={{ $json.session.fecha_sesion }}" }, { "fieldId": "estado", "fieldValue": "notificado" }, { "fieldId": "sesion_id", "fieldValue": "={{ $json.session.id }}" }, { "fieldId": "pais", "fieldValue": "={{ $('Get an employee1').item.json.location }}" }, { "fieldId": "division", "fieldValue": "={{ $('Get an employee1').item.json.division }}" }, { "fieldId": "puesto", "fieldValue": "={{ $('Get an employee1').item.json.jobTitle }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2496, 448 ], "id": "f2aca2bd-e72d-4457-9a6b-c4b0f8bcc558", "name": "Actualizar datos del empleado y sesion asignada1", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/conferenceRecords", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 64, 2752 ], "id": "602289b9-3c7d-4ced-b507-b27401ed9910", "name": "Obtener conferenceRecord", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAR2K6i8Y/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=yOTYTZ6rayK3NlOworCkaKMPCqssxjbokfKY3wFjeXg", "sendHeaders": true, "headerParameters": { "parameters": [ {} ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1840, 1824 ], "id": "11458855-2bd1-4778-81f6-efe07ee1ee8b", "name": "Enviar al espacio de prueba", "retryOnFail": true }, { "parameters": { "operation": "get", "contactId": "={{ $json.idLimpio }}", "fields": [ "emailAddresses", "names" ] }, "type": "n8n-nodes-base.googleContacts", "typeVersion": 1, "position": [ 528, 2144 ], "id": "1382bd89-9dd0-4fd5-a78d-853ac02840fb", "name": "Get a contact", "credentials": { "googleContactsOAuth2Api": { "id": "Qmeljx6s3HU998tB", "name": "Eidan - Google Contacts account" } } }, { "parameters": { "jsCode": "// 1. Obtenemos la lista de miembros del nodo anterior\n// Nota: Ajusta 'memberships' si tu JSON viene estructurado de otra forma\nconst memberships = $input.first().json.memberships || [];\n\n// 2. Mapeamos y limpiamos cada usuario\nconst usuariosLimpios = memberships.map(item => {\n const fullUserPath = item.member.name; // Ej: \"users/117120277440258194844\"\n \n // Reemplazamos \"users/\" por nada para dejar solo el número\n const idLimpio = fullUserPath.replace('users/', ''); \n \n return {\n json: {\n idOriginal: fullUserPath,\n idLimpio: idLimpio,\n role: item.role,\n type: item.member.type\n }\n };\n});\n\n// 3. Devolvemos la lista para que n8n los procese en lote\nreturn usuariosLimpios;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 352, 2144 ], "id": "41e5b9fd-598f-4dfb-b7f6-53d473ec1d71", "name": "Limpiar id" }, { "parameters": { "jsCode": "const today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst sessions = $input.all();\n\nfunction parseSessionDate(dateStr) {\n if (!dateStr) return null;\n // Intenta parsear directamente o por partes\n const parsed = new Date(dateStr);\n if (!isNaN(parsed.getTime())) return parsed;\n\n const [day, month] = dateStr.split(' ');\n const year = new Date().getFullYear();\n return new Date(`${month} ${day}, ${year}`);\n}\n\nfunction formatDate(date) {\n const day = date.getDate();\n const month = date.toLocaleString('en-US', { month: 'long' });\n return `${day} ${month}`;\n}\n\nlet matchedSession = null;\n\nfor (const item of sessions) {\n const rawDate = parseSessionDate(item.json.fecha_sesion);\n if (!rawDate || isNaN(rawDate.getTime())) continue;\n\n // Creamos una copia para no alterar la fecha original\n const sessionDate = new Date(rawDate.getTime());\n sessionDate.setHours(0, 0, 0, 0);\n\n if (sessionDate.getTime() === today.getTime()) {\n matchedSession = item;\n break;\n }\n}\n\nreturn [\n {\n json: {\n today: formatDate(today),\n foundSession: !!matchedSession,\n session: matchedSession?.json ?? null\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 688, 2144 ], "id": "aa48e478-2800-4462-b8a5-fb4651701b2d", "name": "Unir datos2" }, { "parameters": { "url": "=https://chat.googleapis.com/v1/spaces/AAQAgX1mjaY/members", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleChatOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 192, 2144 ], "id": "7e8c9e23-1bfb-4111-983d-898eb43f4981", "name": "Obtener miembros", "retryOnFail": true, "credentials": { "googleChatOAuth2Api": { "id": "Tg9EZ8oKp4hqoWvX", "name": "Eidan - Chat account" } } }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Sin título\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con los datos de la sesión\nconst body = {\n text: `🔔 *Recordatorio de #TheGLMWay para hoy* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"🎓 Sesión de Capacitación\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Tema: ${titulo}
` +\n `Participantes inscritos: ${totalParticipantes} personas`\n }\n },\n {\n textParagraph: {\n text: `👉 Entrar a la reunión aquí`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2032 ], "id": "18d7cd2e-ba38-4c1b-b2e1-f3db9fe301d5", "name": "Formatear datos espanol" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Untitled\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con los datos de la sesión\nconst body = {\n text: `🔔 *#TheGLMWay Reminder for today* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"🎓 Training Session\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Topic: ${titulo}
` +\n `Registered participants: ${totalParticipantes} people`\n }\n },\n {\n textParagraph: {\n text: `👉 Join the meeting here`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 1872 ], "id": "36ad61bf-4d83-42f8-987e-8b8216115a67", "name": "Formatear datos ingles" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "EN", "operator": { "type": "string", "operation": "equals" }, "id": "a6a13143-17cd-4020-b789-726c8faae456" } ], "combinator": "and" } }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "5ffc2081-5b80-4d72-96fc-121dc727683a", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "ES", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" } } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ 1088, 1952 ], "id": "afe4c647-cec2-4cb4-84c5-4b52914ced09", "name": "Es espanol o ingles1" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "EN", "operator": { "type": "string", "operation": "equals" }, "id": "a6a13143-17cd-4020-b789-726c8faae456" } ], "combinator": "and" } }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "5ffc2081-5b80-4d72-96fc-121dc727683a", "leftValue": "={{ $('Calcular sesion mas cercana4').item.json.session.idioma }}", "rightValue": "ES", "operator": { "type": "string", "operation": "equals", "name": "filter.operator.equals" } } ], "combinator": "and" } } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ 1104, 2288 ], "id": "17143de2-2245-45a8-b5db-06d73aa2104f", "name": "Es espanol o ingles" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular sesion mas cercana4\"\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Sin título\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Contar participantes sumando los de todos los países de forma dinámica\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con el aviso de que no hay participantes\nconst body = {\n text: `🔔 *Aviso de sesión sin participantes* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"⚠️ Sesión de Capacitación\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Tema: ${titulo}
\\n` +\n `No se han registrado participantes para la capacitación de hoy, por lo que no es necesario que te conectes.`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2368 ], "id": "953f5fb0-8eea-40f7-8910-a1da77516176", "name": "Formatear datos espanol1" }, { "parameters": { "jsCode": "// 1. Get session data from the \"Calcular sesion mas cercana4\" node\nconst sessionNode = $('Calcular sesion mas cercana4').first();\nconst session = sessionNode?.json?.session || {};\nconst titulo = session.titulo || \"Untitled\";\nconst horaInicio = session.hora_inicio || \"--:--\";\nconst horaFin = session.hora_fin || \"--:--\";\nconst enlace = session.enlace_reunion || \"\";\n\n// 2. Count participants by dynamically summing all countries\nlet totalParticipantes = 0;\nif (session.participantes) {\n Object.keys(session.participantes).forEach(pais => {\n const listaPais = session.participantes[pais];\n if (Array.isArray(listaPais)) {\n totalParticipantes += listaPais.length;\n }\n });\n}\n\n// 3. Get contactId from the previous node to generate mentions\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos2').all();\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Build the message body with the notice of no participants\nconst body = {\n text: `🔔 *No participants for today's training* \\n\\nInstructor: ${menciones}`,\n cardsV2: [\n {\n cardId: \"session-reminder\",\n card: {\n header: {\n title: \"⚠️ Training Session\"\n },\n sections: [\n {\n widgets: [\n {\n textParagraph: {\n text: `Topic: ${titulo}
\\n` +\n `No participants have registered for today's training, so you do not need to connect.`\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1296, 2208 ], "id": "adb8c1b5-1696-49b1-aa2d-8b329846c007", "name": "Formatear datos ingles1" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAgX1mjaY/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=drBaE6ZeBbHhPKCmJd_odP3UcYcq4Ie64JXmbI29Vp8", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1520, 2128 ], "id": "db80a48f-bf0b-4b4e-a1d6-06c9da6c188c", "name": "Enviar notifacion a glmway notificaciones", "retryOnFail": true }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular falta 48h o 24h1\"\nconst sessionNode = $('Calcular falta 48h o 24h1').first();\nconst sesion = sessionNode?.json?.sesion || {}; // Leído desde la raíz del JSON\n\n// 2. Contar participantes y construir de forma dinámica la lista por país\nlet totalParticipantes = 0;\nlet listaParticipantesTexto = \"\";\n\nif (sesion.participantes) {\n Object.keys(sesion.participantes).forEach(pais => {\n const listaPais = sesion.participantes[pais];\n if (Array.isArray(listaPais) && listaPais.length > 0) {\n totalParticipantes += listaPais.length;\n \n // Añadir el encabezado del país\n listaParticipantesTexto += `
📍 ${pais} (${listaPais.length}):
`;\n \n // Listar cada participante de ese país\n listaPais.forEach(p => {\n listaParticipantesTexto += `• ${p.nombre} (${p.departamento || 'Sin Depto'} | ${p.division || 'Sin Division'})
`;\n });\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones de los coordinadores\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos3').all(); // Asegúrate de verificar si tu nodo se llama Unir datos3 o similar\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con formato Google Chat Card\nconst body = {\n text: `🔔 *Aviso para Coordinadores RRHH* \\nEstimados ${menciones}, aquí está el listado de personas inscritas para la capacitación de mañana.`,\n cardsV2: [\n {\n cardId: \"session-reminder-hr\",\n card: {\n header: {\n title: `🎓 Capacitación #TheGLMWay de mañana`,\n },\n sections: [\n {\n header: \"📈 Resumen de Asistencia\",\n widgets: [\n {\n textParagraph: {\n text: `Total inscritos: ${totalParticipantes} personas
` + \n listaParticipantesTexto\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1744, 1584 ], "id": "87ace248-4ea5-406f-89da-88d450ad413e", "name": "Formatear datos espanol2" }, { "parameters": { "jsCode": "// 1. Obtener datos de la sesión del nodo \"Calcular falta 48h o 24h1\"\nconst sessionNode = $('Calcular falta 48h o 24h1').first();\nconst sesion = sessionNode?.json?.sesion || {}; // Leído desde la raíz del JSON\n\n// 2. Contar participantes y construir de forma dinámica la lista por país\nlet totalParticipantes = 0;\nlet listaParticipantesTexto = \"\";\n\nif (sesion.participantes) {\n Object.keys(sesion.participantes).forEach(pais => {\n const listaPais = sesion.participantes[pais];\n if (Array.isArray(listaPais) && listaPais.length > 0) {\n totalParticipantes += listaPais.length;\n \n // Añadir el encabezado del país\n listaParticipantesTexto += `
📍 ${pais} (${listaPais.length}):
`;\n \n // Listar cada participante de ese país\n listaPais.forEach(p => {\n listaParticipantesTexto += `• ${p.nombre} (${p.departamento || 'Sin Depto'} | ${p.division || 'Sin Division'})
`;\n });\n }\n });\n}\n\n// 3. Obtener los contactId del nodo anterior para generar las menciones de los coordinadores\nlet menciones = \"\";\ntry {\n const itemsUnirDatos = $('Unir datos3').all(); // Asegúrate de verificar si tu nodo se llama Unir datos3 o similar\n const idsUnicos = [...new Set(\n itemsUnirDatos\n .map(item => item.json.contactId)\n .filter(id => id !== undefined && id !== null && id !== \"\")\n )];\n menciones = idsUnicos.map(id => ``).join(\" \");\n} catch (error) {\n menciones = \"\";\n}\n\n// 4. Construir cuerpo del mensaje con formato Google Chat Card\nconst body = {\n text: `🔔 *HR Coordinator Notification* \\nDear ${menciones}, here is the list of people registered for tomorrow's session.`,\n cardsV2: [\n {\n cardId: \"session-reminder-hr\",\n card: {\n header: {\n title: `🎓 Tomorrow's #TheGLMWay Training`,\n },\n sections: [\n {\n header: \"📈 Attendance Summary\",\n widgets: [\n {\n textParagraph: {\n text: `Total registered: ${totalParticipantes} people
` + \n listaParticipantesTexto\n }\n }\n ]\n }\n ]\n }\n }\n ]\n};\n\nreturn [{ json: body }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1744, 1408 ], "id": "bb4cbe19-9364-4c83-a309-5594d9c5a26b", "name": "Formatear datos ingles2" }, { "parameters": { "jsCode": "// Obtener todos los elementos que entran al nodo\nconst items = $input.all();\n\nconst hoy = new Date();\nhoy.setHours(0, 0, 0, 0);\n\nlet mejorItem = null;\nlet menorDiferencia = Infinity;\nlet mejorFechaHoyStr = '';\n\n// Recorrer cada sesión para calcular cuál es la más cercana\nfor (const item of items) {\n const fecha_sesion = item.json.fecha_sesion;\n if (!fecha_sesion) continue;\n\n // Crear la fecha de la sesión usando el año actual\n let sesion = new Date(`${fecha_sesion} ${hoy.getFullYear()}`);\n sesion.setHours(0, 0, 0, 0);\n\n // Si la fecha ya pasó este año, se toma la del año que viene\n if (sesion < hoy) {\n sesion = new Date(`${fecha_sesion} ${hoy.getFullYear() + 1}`);\n sesion.setHours(0, 0, 0, 0);\n }\n\n // Calcular diferencia en días\n const diferenciaDias = Math.floor((sesion - hoy) / (1000 * 60 * 60 * 24));\n\n // Si esta sesión es más cercana que las anteriores analizadas, la guardamos\n if (diferenciaDias < menorDiferencia) {\n menorDiferencia = diferenciaDias;\n mejorItem = item.json;\n mejorFechaHoyStr = hoy.toLocaleDateString('en-GB', {\n day: 'numeric',\n month: 'long'\n });\n }\n}\n\n// Si no se encontró ninguna sesión válida, no devuelve nada\nif (!mejorItem) return [];\n\n// Retorna únicamente la sesión más cercana encontrada\nreturn [\n {\n json: {\n sesion: mejorItem,\n fecha_hoy: mejorFechaHoyStr,\n diferenciaDias: menorDiferencia\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 0, 1504 ], "id": "47542a5b-ebe1-4e85-8229-bb9aa7e1b744", "name": "Calcular falta 48h o 24h1" }, { "parameters": { "operation": "get", "contactId": "={{ $json.idLimpio }}", "fields": [ "emailAddresses", "names" ] }, "type": "n8n-nodes-base.googleContacts", "typeVersion": 1, "position": [ 1200, 1488 ], "id": "f49640d2-f7a0-43da-b9e1-1da5dbe93a22", "name": "Get a contact1", "credentials": { "googleContactsOAuth2Api": { "id": "Qmeljx6s3HU998tB", "name": "Eidan - Google Contacts account" } } }, { "parameters": { "jsCode": "// 1. Obtenemos la lista de miembros del nodo anterior\n// Nota: Ajusta 'memberships' si tu JSON viene estructurado de otra forma\nconst memberships = $input.first().json.memberships || [];\n\n// 2. Mapeamos y limpiamos cada usuario\nconst usuariosLimpios = memberships.map(item => {\n const fullUserPath = item.member.name; // Ej: \"users/117120277440258194844\"\n \n // Reemplazamos \"users/\" por nada para dejar solo el número\n const idLimpio = fullUserPath.replace('users/', ''); \n \n return {\n json: {\n idOriginal: fullUserPath,\n idLimpio: idLimpio,\n role: item.role,\n type: item.member.type\n }\n };\n});\n\n// 3. Devolvemos la lista para que n8n los procese en lote\nreturn usuariosLimpios;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1024, 1488 ], "id": "c17d8ecc-45f9-4c03-a4d4-88d90ae8a3ec", "name": "Limpiar id1" }, { "parameters": { "jsCode": "// 1. Forzar la lectura del nodo de coordinadores\nconst itemsCoordinadores = $('Matchear coordinador y pais inscrito').all();\n\n// 2. Obtener todos los contactos cargados de \"Get a contact1\"\nconst contacts = $('Get a contact1').all();\n\nconst resultado = [];\n\n// Función para limpiar tildes, espacios y pasarlo a minúsculas\nconst limpiarTexto = (texto) => \n texto ? texto.toLowerCase().normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\").trim() : \"\";\n\n// 3. Procesar la lista de coordinadores\nfor (const item of itemsCoordinadores) {\n const coordinadorNombre = item.json.coordinador?.nombre;\n const paisCoordinador = item.json.pais; // Extraemos el país\n if (!coordinadorNombre) continue;\n\n const coordinadorClean = limpiarTexto(coordinadorNombre);\n\n // 4. Buscar coincidencias en los contactos de Google\n const matchingContacts = contacts.filter(c => {\n const displayName = c.json.names?.displayName;\n if (!displayName) return false;\n\n const displayNameClean = limpiarTexto(displayName);\n return displayNameClean === coordinadorClean || displayNameClean.includes(coordinadorClean) || coordinadorClean.includes(displayNameClean);\n });\n\n // 5. Guardar los resultados encontrados incluyendo el país\n for (const contactItem of matchingContacts) {\n resultado.push({\n json: {\n pais: paisCoordinador,\n nombre_detectado: contactItem.json.names.displayName,\n contactId: contactItem.json.contactId\n }\n });\n }\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1360, 1488 ], "id": "73de340f-189b-4963-bdf6-9b1bfd603cd6", "name": "Unir datos3" }, { "parameters": { "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/members", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleChatOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 864, 1488 ], "id": "949eb6ae-2aba-43d2-a262-f91313336d2f", "name": "Obtener miembros RRHH Notificaciones", "retryOnFail": true, "credentials": { "googleChatOAuth2Api": { "id": "Tg9EZ8oKp4hqoWvX", "name": "Eidan - Chat account" } } }, { "parameters": { "operation": "get", "tableId": "coordinadores_rrhh_glmway", "filters": { "conditions": [ { "keyName": "pais", "keyValue": "={{ $('Get an employee').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 736, -352 ], "id": "aeb15925-1828-426e-a437-809aee1df732", "name": "Obtener coordinador3", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "get", "tableId": "coordinadores_rrhh_glmway", "filters": { "conditions": [ { "keyName": "pais", "keyValue": "={{ $('Get an employee1').item.json.location }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1136, 256 ], "id": "e909b37d-a192-4845-b80f-fb1b245a6614", "name": "Obtener coordinador4", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/{{ $json.name }}/participants", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 432, 2752 ], "id": "c05fc7b5-5d4e-403b-aa67-49b7427f9b04", "name": "Obtener participantes", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "operation": "get", "tableId": "sesiones_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion", "keyValue": "={{ $('Hora de la reunion').first().json.fechaCorta }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 832, 2752 ], "id": "e4115807-580d-4075-8d62-de14c174c43a", "name": "Obtener sesion2", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "// 1. Obtener la lista de nombres detectados en la reunión\nconst personasDetectadas = $('Detectar participantes en la sesion').all();\nconst nombresDetectados = personasDetectadas.map(item => item.json.displayName).filter(Boolean);\n\n// 2. Obtener los datos de la sesión (se toma el primer item del nodo)\nconst datosSesion = $('Obtener sesion2').first().json;\nconst participantesPorPais = datosSesion.participantes || {};\n\n// Normalizar texto: convierte a minúsculas y remueve acentos/diacríticos\nfunction normalizar(texto) {\n if (!texto) return \"\";\n return texto\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .toLowerCase()\n .trim();\n}\n\n// Función para determinar si un nombre detectado corresponde a la persona registrada\nfunction esMismaPersona(nombreDetectado, nombreRegistrado) {\n const normDetectado = normalizar(nombreDetectado);\n const normRegistrado = normalizar(nombreRegistrado);\n\n if (!normDetectado || !normRegistrado) return false;\n\n // Separar en palabras ignorando conectores o palabras cortas (\"de\", \"del\", \"la\")\n const palabrasDetectadas = normDetectado.split(/\\s+/).filter(p => p.length > 2);\n const palabrasRegistradas = normRegistrado.split(/\\s+/).filter(p => p.length > 2);\n\n if (palabrasDetectadas.length === 0) return false;\n\n // Cuenta cuántas palabras del nombre detectado coinciden con el nombre completo registrado\n const coincidencias = palabrasDetectadas.filter(pDetectada => \n palabrasRegistradas.some(pRegistrada => pRegistrada.includes(pDetectada) || pDetectada.includes(pRegistrada))\n ).length;\n\n // Si el nombre detectado tiene 1 o 2 palabras, exige que al menos 1 o 2 coincidan.\n // Si tiene más de 2 palabras, exige al menos 2 coincidencias.\n if (palabrasDetectadas.length <= 2) {\n return coincidencias >= Math.min(palabrasDetectadas.length, 2);\n }\n return coincidencias >= 2;\n}\n\n// 3. Procesar a todos los participantes registrados por país\nconst todosLosParticipantes = [];\n\nObject.entries(participantesPorPais).forEach(([pais, listaPersonas]) => {\n if (Array.isArray(listaPersonas)) {\n listaPersonas.forEach(persona => {\n if (persona && persona.nombre && persona.nombre.trim() !== \"\") {\n\n // Comprobar si el participante asistió según la lista detectada\n const asistio = nombresDetectados.some(nombreDetectado =>\n esMismaPersona(nombreDetectado, persona.nombre)\n );\n\n todosLosParticipantes.push({\n pais: pais,\n nombreCompleto: persona.nombre,\n correo: persona.correo || \"\",\n division: persona.division || \"\",\n departamento: persona.departamento || \"\",\n asistio: asistio\n });\n }\n });\n }\n});\n\n// 4. Retornar respuesta unificada\nreturn [\n {\n json: {\n tituloSesion: datosSesion.titulo,\n fechaSesion: datosSesion.fecha_sesion,\n totalParticipantes: todosLosParticipantes.length,\n asistentes: todosLosParticipantes.filter(p => p.asistio).length,\n inasistentes: todosLosParticipantes.filter(p => !p.asistio).length,\n participantes: todosLosParticipantes\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1328, 2752 ], "id": "2e7c7d5a-13bf-40a0-bdf8-1f2f5b07188b", "name": "Buscar participantes" }, { "parameters": { "fieldToSplitOut": "participantes", "options": {} }, "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 1488, 2752 ], "id": "8b9471a9-f616-414d-988a-8f9914d72db3", "name": "Split Out" }, { "parameters": { "rule": { "interval": [ { "field": "weeks", "triggerAtDay": [ 3 ], "triggerAtHour": 19, "triggerAtMinute": 50 } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.3, "position": [ -304, 2752 ], "id": "58146359-aef8-4a96-9f1c-9bc6987ce7f4", "name": "Schedule Trigger7" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "fecha_sesion_inscrito", "condition": "eq", "keyValue": "={{ $json.fecha_sesion }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "instructor", "fieldValue": "={{ $json.instructor }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1328, 2992 ], "id": "982ec4df-b792-46b9-bce5-ab6e8709a2a8", "name": "Actualizar instructor de inscritos", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "nombre", "condition": "fullText", "searchFunction": "wfts", "keyValue": "={{ $json.nombreCompleto }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "asistio_evento_glmway", "fieldValue": "={{ $json.asistio }}" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 1648, 2752 ], "id": "d93b4d14-106f-4d05-b397-78ec6d0dc522", "name": "Actualizar asistencia", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } }, { "parameters": { "jsCode": "// Obtener todos los items del nodo \"Obtener participantes\"\nconst items = $('Obtener participantes').all();\n\nconst resultado = [];\n\nfor (const item of items) {\n const participants = item.json.participants || [];\n\n for (const participant of participants) {\n if (participant.signedinUser) {\n resultado.push({\n json: {\n displayName: participant.signedinUser.displayName,\n user: participant.signedinUser.user\n }\n });\n }\n }\n}\n\nreturn resultado;" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 640, 2752 ], "id": "73c64bc3-4321-46d6-9d5b-ef74bd385b2c", "name": "Detectar participantes en la sesion" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "9674fd7e-dd62-42d4-8931-6c67e59e3dd7", "leftValue": "={{ $json.pais }}", "rightValue": "Jamaica", "operator": { "type": "string", "operation": "equals" } }, { "id": "32931394-f4ea-4055-b866-906a81988173", "leftValue": "={{ $json.pais }}", "rightValue": "Trinidad and Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "ea2a8466-96c6-460f-b08f-d23c06b2d18c", "leftValue": "={{ $json.pais }}", "rightValue": "Barbados", "operator": { "type": "string", "operation": "equals" } }, { "id": "28e49217-0c1a-4462-9642-676e54926d3e", "leftValue": "={{ $json.pais }}", "rightValue": "Saint Thomas", "operator": { "type": "string", "operation": "equals" } }, { "id": "c6a6aea5-48f4-44dc-92ca-a9f9de9cacf9", "leftValue": "={{ $json.pais }}", "rightValue": "St. Croix", "operator": { "type": "string", "operation": "equals" } }, { "id": "e6f52339-ea7c-462f-bdc2-8b7353160e4c", "leftValue": "={{ $json.pais }}", "rightValue": "Tobago", "operator": { "type": "string", "operation": "equals" } }, { "id": "b308c2b6-53b4-4d49-b540-cdc03e36528b", "leftValue": "={{ $json.pais }}", "rightValue": "Guyana", "operator": { "type": "string", "operation": "equals" } }, { "id": "35a50a33-a2b5-4116-9336-11300357569e", "leftValue": "={{ $json.pais }}", "rightValue": "Aruba", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "or" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ 2192, 2752 ], "id": "5df50d37-798a-42f8-ab7b-2ae3f05610fd", "name": "Pais?4" }, { "parameters": { "jsCode": "// Retorna solo el primer nombre de cada participante\nconst items = $input.all();\n\nreturn items.map(item => {\n const nombreCompleto = item.json.nombre || \"\";\n const primerNombre = nombreCompleto.trim().split(/\\s+/)[0] || \"\";\n\n return {\n json: {\n ...item.json,\n primerNombre\n }\n };\n});" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 2048, 2752 ], "id": "9c046113-3694-40f9-819c-42122ec117e5", "name": "Cortar nombre" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "085e7943-f198-4ef9-acab-3c06a3e18cdc", "leftValue": "={{ $json.asistio_evento_glmway }}", "rightValue": false, "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.3, "position": [ 1824, 2752 ], "id": "a2011c37-b133-431b-b8ff-41b6a4bb4f10", "name": "Asistio?" }, { "parameters": { "jsCode": "// Convierte fechas ISO, incluyendo T24:00:00 -> día siguiente T00:00:00\nfunction parseISO(iso) {\n if (!iso.includes(\"T24:\")) {\n return new Date(iso).getTime();\n }\n\n const [datePart, timePart] = iso.split(\"T\");\n const nextDay = new Date(datePart + \"T00:00:00Z\");\n nextDay.setUTCDate(nextDay.getUTCDate() + 1);\n\n const fixedIso = nextDay.toISOString().split(\"T\")[0] + \"T\" + timePart.replace(\"24:\", \"00:\");\n return new Date(fixedIso).getTime();\n}\n\n// Rango objetivo\nconst reunion = $('Hora de la reunion').first().json;\nconst targetStart = parseISO(reunion.startTime);\nconst targetEnd = parseISO(reunion.endTime);\n\n// Fecha objetivo (YYYY-MM-DD)\nconst targetDate = reunion.startTime.split(\"T\")[0];\n\n// Conferencias\nconst conferences = $('Obtener conferenceRecord').first().json.conferenceRecords;\n\n// Filtrar solo conferencias del mismo día\nconst resultado = conferences\n .filter(conf => conf.startTime.split(\"T\")[0] === targetDate)\n .map(conf => {\n const confStart = parseISO(conf.startTime);\n const confEnd = parseISO(conf.endTime);\n\n let distancia;\n\n if (confStart <= targetEnd && confEnd >= targetStart) {\n distancia = 0;\n } else {\n distancia = Math.min(\n Math.abs(confStart - targetEnd),\n Math.abs(confEnd - targetStart)\n );\n }\n\n return {\n json: {\n name: conf.name,\n startTime: conf.startTime,\n endTime: conf.endTime,\n distanciaMs: distancia\n }\n };\n })\n .sort((a, b) => a.json.distanciaMs - b.json.distanciaMs);\n\n// Retornar sin el campo de distancia\nreturn resultado.map(item => ({\n json: {\n name: item.json.name,\n startTime: item.json.startTime,\n endTime: item.json.endTime\n }\n}));" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 240, 2752 ], "id": "881e05b0-c9fd-4799-b828-395b99f92a88", "name": "Buscar sesion con hora UTC" }, { "parameters": { "httpMethod": "POST", "path": "evaluacion-glmway", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -320, 3088 ], "id": "fe7c0429-6070-4181-ad6d-1a5a4888ce66", "name": "Webhook1", "webhookId": "14f1d226-12da-42c2-90d1-4d8fd5620cae" }, { "parameters": { "content": "## Guardar conteo de evaluaciones han sido resueltas", "height": 240, "width": 608, "color": 4 }, "type": "n8n-nodes-base.stickyNote", "position": [ -384, 3008 ], "typeVersion": 1, "id": "7d34e6af-6b75-4780-9f70-848d2045b123", "name": "Sticky Note7" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/incrementar_evaluaciones_resueltas_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -112, 3088 ], "id": "59013746-bac2-4c90-a39e-3d7835ab6c31", "name": "Incrementar conteo de evaluaciones respondidas" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/incrementar_evaluaciones_enviadas_glmway", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 2816, 2768 ], "id": "5b1e1192-2e9b-44b2-9303-194b6266202b", "name": "Incrementar conteo de evaluaciones enviadas" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1952, 1408 ], "id": "5d50cef9-0ebb-4f28-8deb-69c7feb6f62e", "name": "Enviar notificacion a rrhh notificaciones", "retryOnFail": true }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1952, 1584 ], "id": "c83590cd-6e98-4e2d-81f6-6e2f204a948d", "name": "Enviar notificacion a rrhh notificaciones1", "retryOnFail": true }, { "parameters": { "url": "=https://meet.googleapis.com/v2/conferenceRecords", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": { "pagination": { "pagination": { "parameters": { "parameters": [ { "name": "pageToken", "value": "={{ $response.body.nextPageToken }}" } ] }, "paginationCompleteWhen": "other", "completeExpression": "={{ !$response.body.nextPageToken }}" } } } }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 592, 3472 ], "id": "a13dbc58-f474-4eb8-aebb-68e1bf97ff42", "name": "Obtener conferenceRecord1", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "url": "=https://meet.googleapis.com/v2/{{ $json.data[5].name }}/participants", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1264, 3472 ], "id": "08659d49-c234-447c-9262-06f6e099b243", "name": "Obtener participantes1", "credentials": { "googleOAuth2Api": { "id": "0HsSRUm82KPsWdiJ", "name": "Eidan - Google account" } } }, { "parameters": { "method": "POST", "url": "https://backend.composio.dev/api/v3/tools/execute/googlemeet_list_conference_records", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "x-api-key", "value": "ak_LlFK0KrKzU9LBNqvePo9" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "{\n \"entity_id\": \"pg-test-7d008927-9e8c-4d83-afe9-a77b7dc8efd7\",\n \"connected_account_id\": \"ca_zJ0wM5hvfThQ\",\n \"arguments\": {}\n}", "options": { "pagination": { "pagination": { "parameters": { "parameters": [ { "name": "pageToken", "value": "={{ $response.body.nextPageToken }}" } ] }, "paginationCompleteWhen": "other", "completeExpression": "={{ !$response.body.nextPageToken }}" } } } }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1056, 3760 ], "id": "48c3fbf9-48ec-4fd5-8ad0-157f4549d6ee", "name": "Composio - Obtener registro" }, { "parameters": { "method": "POST", "url": "https://backend.composio.dev/api/v3/tools/execute/GOOGLEMEET_LIST_PARTICIPANT_SESSIONS", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "x-api-key", "value": "ak_LlFK0KrKzU9LBNqvePo9" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"entity_id\": \"pg-test-7d008927-9e8c-4d83-afe9-a77b7dc8efd7\",\n \"connected_account_id\": \"ca_zJ0wM5hvfThQ\",\n \"arguments\": {\n \"parent\": \"{{ $json.data.conferenceRecords[9].name }}\"\n }\n} ", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 1280, 3760 ], "id": "fef3abc8-4b8a-47a2-9508-61793ec02566", "name": "Composio - Obtener participantes" }, { "parameters": { "jsCode": "// Diccionario de meses inglés -> español\nconst meses = {\n january: 'Enero',\n february: 'Febrero',\n march: 'Marzo',\n april: 'Abril',\n may: 'Mayo',\n june: 'Junio',\n july: 'Julio',\n august: 'Agosto',\n september: 'Septiembre',\n october: 'Octubre',\n november: 'Noviembre',\n december: 'Diciembre'\n};\n\nconst fecha = $('Pais?2').first().json.session.fecha_sesion;\n\nconst partes = fecha.trim().split(' ');\nconst dia = partes[0];\nconst mesIngles = partes[1].toLowerCase();\nconst mesEspanol = meses[mesIngles] || partes[1];\n\nconst fechaFormateada = `${mesEspanol} ${dia}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 960, 752 ], "id": "e41d24f2-67d7-410a-a0b6-87a0302b6c11", "name": "Convertir fecha a espanol2" }, { "parameters": { "jsCode": "function getOrdinalSuffix(dia) {\n const d = parseInt(dia, 10);\n if (d > 3 && d < 21) return `${d}th`; // 11th-13th excepción cubierta aquí\n switch (d % 10) {\n case 1: return `${d}st`;\n case 2: return `${d}nd`;\n case 3: return `${d}rd`;\n default: return `${d}th`;\n }\n}\n\nconst fecha = $('Pais?2').first().json.fecha_sesion; // Cambia \"fecha\" por el nombre real de tu campo\nconst partes = fecha.trim().split(' '); // [\"8\", \"July\"]\n\nconst dia = partes[0];\nconst mes = partes[1];\nconst diaConSufijo = getOrdinalSuffix(dia);\n\nconst fechaFormateada = `${mes} ${diaConSufijo}`;\n\nreturn [\n {\n json: {\n fechaFormateada\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 960, 960 ], "id": "c452dd02-ecb8-4b2a-a179-bbd08faf01ef", "name": "Convertir fecha a ingles2" }, { "parameters": { "fieldToSplitOut": "conferenceRecords", "options": {} }, "type": "n8n-nodes-base.splitOut", "typeVersion": 1, "position": [ 800, 3472 ], "id": "9db65bec-8550-488d-ab1c-b5559878c381", "name": "Split Out1" }, { "parameters": { "aggregate": "aggregateAllItemData", "options": {} }, "type": "n8n-nodes-base.aggregate", "typeVersion": 1, "position": [ 992, 3472 ], "id": "7bbaf7f0-2451-4120-b94a-56e8628fff9e", "name": "Aggregate2" }, { "parameters": { "method": "POST", "url": "=https://chat.googleapis.com/v1/spaces/AAQAQj1t9AA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Bjwcj-R0V8RsffMTHW0JovFcjotMghLp8bQ-40sxyfI", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1776, 2128 ], "id": "a2c3da31-9918-42f2-a71b-9fdfdc09d63d", "name": "Enviar notificacion a rrhh notificaciones2", "retryOnFail": true }, { "parameters": { "jsCode": "const timestamp = $input.first().json.timestamp;\n\n// Extraer solo la fecha YYYY-MM-DD\nconst fecha = timestamp.split(\"T\")[0];\n\nconst startTime = fecha + \"T22:50:24.833266Z\";\nconst endTime = fecha + \"T24:00:00.833266Z\";\n\n// Crear objeto Date forzando la hora a mediodía para evitar saltos de zona horaria\nconst fechaObj = new Date(fecha + \"T12:00:00Z\");\n\nconst dia = fechaObj.getUTCDate();\nconst mes = fechaObj.toLocaleString(\"en-US\", { month: \"long\", timeZone: \"UTC\" });\n\nconst fechaCorta = `${dia} ${mes}`;\n\nreturn [\n {\n json: {\n startTime,\n endTime,\n fechaCorta\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -112, 2752 ], "id": "e78ee155-4c33-419e-a3f8-1ef0631357a6", "name": "Hora de la reunion" }, { "parameters": { "operation": "update", "tableId": "inscritos_glmway", "filters": { "conditions": [ { "keyName": "empleado_id", "condition": "eq", "keyValue": "={{ $('Cortar nombre').item.json.empleado_id }}" } ] }, "fieldsUi": { "fieldValues": [ { "fieldId": "estado", "fieldValue": "evaluacion_enviada" } ] } }, "type": "n8n-nodes-base.supabase", "typeVersion": 1, "position": [ 2624, 2768 ], "id": "b7c02e2f-1382-4086-9059-cf75fee9d278", "name": "Actualizar estado a evaluacion_enviada", "credentials": { "supabaseApi": { "id": "2PlsR6rpK7rQTIEn", "name": "Sofia test - Supabase account" } } } ], "connections": { "Webhook": { "main": [ [ { "node": "Get an employee", "type": "main", "index": 0 } ] ] }, "When clicking ‘Execute workflow’": { "main": [ [ { "node": "Valores", "type": "main", "index": 0 } ] ] }, "Obtener archivo": { "main": [ [ { "node": "Get a workflow1", "type": "main", "index": 0 } ], [ { "node": "Get a workflow2", "type": "main", "index": 0 } ] ] }, "Get a workflow1": { "main": [ [ { "node": "Code in JavaScript2", "type": "main", "index": 0 } ] ] }, "Get a workflow2": { "main": [ [ { "node": "Code in JavaScript4", "type": "main", "index": 0 } ] ] }, "Valores": { "main": [ [ { "node": "Obtener archivo", "type": "main", "index": 0 } ] ] }, "Code in JavaScript2": { "main": [ [ { "node": "Actualizar archivo", "type": "main", "index": 0 } ] ] }, "Code in JavaScript4": { "main": [ [ { "node": "Subir archivo", "type": "main", "index": 0 } ] ] }, "Get an employee": { "main": [ [ { "node": "Informacion extra del empleado", "type": "main", "index": 0 } ] ] }, "Informacion extra del empleado": { "main": [ [ { "node": "Calcular fecha hireDate", "type": "main", "index": 0 } ] ] }, "Entra hoy?": { "main": [ [ { "node": "Obtener coordinador3", "type": "main", "index": 0 } ], [ { "node": "Insertar a inscritos (inactivo)", "type": "main", "index": 0 } ] ] }, "Calcular fecha hireDate": { "main": [ [ { "node": "Tiene correo y pais?", "type": "main", "index": 0 } ] ] }, "Hay coordinador?": { "main": [ [ { "node": "Pais?", "type": "main", "index": 0 } ], [ { "node": "Alerta no hay coordinador RRHH", "type": "main", "index": 0 } ] ] }, "Schedule Trigger1": { "main": [ [ { "node": "Obtener inactivos", "type": "main", "index": 0 } ] ] }, "Get an employee1": { "main": [ [ { "node": "Informacion extra del empleado1", "type": "main", "index": 0 } ] ] }, "Informacion extra del empleado1": { "main": [ [ { "node": "Calcular fecha hireDate1", "type": "main", "index": 0 } ] ] }, "Loop Over Items": { "main": [ [], [ { "node": "Get an employee1", "type": "main", "index": 0 } ] ] }, "Calcular fecha hireDate1": { "main": [ [ { "node": "Tiene correo y pais?1", "type": "main", "index": 0 } ] ] }, "Entra hoy?1": { "main": [ [ { "node": "Obtener coordinador4", "type": "main", "index": 0 } ], [ { "node": "Wait2", "type": "main", "index": 0 } ] ] }, "Pais?1": { "main": [ [ { "node": "Crear variable idioma ES1", "type": "main", "index": 0 } ], [ { "node": "Crear variable idioma EN1", "type": "main", "index": 0 } ] ] }, "Hay coordinador?1": { "main": [ [ { "node": "Pais?1", "type": "main", "index": 0 } ], [ { "node": "Alerta no hay coordinador RRHH1", "type": "main", "index": 0 } ] ] }, "Pais?": { "main": [ [ { "node": "Crear variable idioma ES", "type": "main", "index": 0 } ], [ { "node": "Crear variable idioma EN", "type": "main", "index": 0 } ] ] }, "Send a message ingles1": { "main": [ [ { "node": "Registrar empleado a la sesion3", "type": "main", "index": 0 } ] ] }, "Send a message espanol1": { "main": [ [ { "node": "Registrar empleado a la sesion2", "type": "main", "index": 0 } ] ] }, "Wait": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Schedule Trigger2": { "main": [ [ { "node": "Obtener notificados", "type": "main", "index": 0 } ] ] }, "Obtener inactivos": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Loop Over Items1": { "main": [ [], [ { "node": "Calcular falta 24h o es el mismo dia", "type": "main", "index": 0 } ] ] }, "Pais?2": { "main": [ [ { "node": "Convertir fecha a espanol2", "type": "main", "index": 0 } ], [ { "node": "Convertir fecha a ingles2", "type": "main", "index": 0 } ] ] }, "Send a message espanol2": { "main": [ [ { "node": "Actualizar estado a recordado", "type": "main", "index": 0 } ] ] }, "Send a message ingles2": { "main": [ [ { "node": "Actualizar estado a recordado", "type": "main", "index": 0 } ] ] }, "Crear variable idioma ES": { "main": [ [ { "node": "Obtener sesiones español", "type": "main", "index": 0 } ] ] }, "Crear variable idioma EN": { "main": [ [ { "node": "Obtener sesiones ingles", "type": "main", "index": 0 } ] ] }, "Obtener sesiones español": { "main": [ [ { "node": "Calcular sesion mas cercana", "type": "main", "index": 0 } ] ] }, "Obtener sesiones ingles": { "main": [ [ { "node": "Calcular sesion mas cercana1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana": { "main": [ [ { "node": "Guardar datos del empleado y sesion asignada", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana1": { "main": [ [ { "node": "Guardar datos del empleado y sesion asignada1", "type": "main", "index": 0 } ] ] }, "Crear variable idioma ES1": { "main": [ [ { "node": "Obtener sesiones español1", "type": "main", "index": 0 } ] ] }, "Crear variable idioma EN1": { "main": [ [ { "node": "Obtener sesiones ingles1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana2": { "main": [ [ { "node": "Actualizar datos del empleado y sesion asignada", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana3": { "main": [ [ { "node": "Actualizar datos del empleado y sesion asignada1", "type": "main", "index": 0 } ] ] }, "Guardar datos del empleado y sesion asignada": { "main": [ [ { "node": "Convertir fecha a espanol", "type": "main", "index": 0 } ] ] }, "Guardar datos del empleado y sesion asignada1": { "main": [ [ { "node": "Convertir fecha a ingles", "type": "main", "index": 0 } ] ] }, "Obtener sesiones español1": { "main": [ [ { "node": "Calcular sesion mas cercana2", "type": "main", "index": 0 } ] ] }, "Obtener sesiones ingles1": { "main": [ [ { "node": "Calcular sesion mas cercana3", "type": "main", "index": 0 } ] ] }, "Alerta no hay coordinador RRHH1": { "main": [ [ { "node": "Pais?1", "type": "main", "index": 0 } ] ] }, "Wait2": { "main": [ [ { "node": "Loop Over Items", "type": "main", "index": 0 } ] ] }, "Obtener notificados": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Falta 24h para el evento?": { "main": [ [ { "node": "Obtener sesion", "type": "main", "index": 0 } ], [ { "node": "Wait1", "type": "main", "index": 0 } ] ] }, "Wait1": { "main": [ [ { "node": "Loop Over Items1", "type": "main", "index": 0 } ] ] }, "Actualizar estado a recordado": { "main": [ [ { "node": "Wait1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger3": { "main": [ [ { "node": "Obtener sesiones", "type": "main", "index": 0 } ] ] }, "Pais?3": { "main": [ [ { "node": "Formatear datos ingles2", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol2", "type": "main", "index": 0 } ] ] }, "Calcular falta 24h o es el mismo dia": { "main": [ [ { "node": "Falta 24h para el evento?", "type": "main", "index": 0 } ] ] }, "Schedule Trigger4": { "main": [ [ { "node": "Obtener entrenamientos ingles y espanol", "type": "main", "index": 0 } ] ] }, "Insertar fechas": { "main": [ [] ] }, "Wait4": { "main": [ [ { "node": "Insertar fechas", "type": "main", "index": 0 } ] ] }, "Borrar fechas": { "main": [ [ { "node": "Wait4", "type": "main", "index": 0 } ] ] }, "Send a message ingles4": { "main": [ [ { "node": "Actualizar estado a evaluacion_enviada", "type": "main", "index": 0 } ] ] }, "Send a message espanol4": { "main": [ [ { "node": "Actualizar estado a evaluacion_enviada", "type": "main", "index": 0 } ] ] }, "Obtener entrenamientos ingles y espanol": { "main": [ [ { "node": "Formatear fecha", "type": "main", "index": 0 } ] ] }, "Formatear fecha": { "main": [ [ { "node": "Borrar fechas", "type": "main", "index": 0 } ] ] }, "Schedule Trigger5": { "main": [ [ { "node": "Obtener coordinadores", "type": "main", "index": 0 } ] ] }, "Obtener entrenamientos ingles y espanol1": { "main": [ [ { "node": "Formatear fecha y detectar idioma", "type": "main", "index": 0 } ] ] }, "Obtener coordinadores": { "main": [ [ { "node": "Aggregate", "type": "main", "index": 0 } ] ] }, "Aggregate": { "main": [ [ { "node": "Insertar/actualizar coordinadores a la bd", "type": "main", "index": 0 } ] ] }, "Aggregate1": { "main": [ [ { "node": "Insertar fechas1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger6": { "main": [ [ { "node": "Obtener fechas e instructores", "type": "main", "index": 0 }, { "node": "Obtener entrenamientos ingles y espanol1", "type": "main", "index": 0 } ] ] }, "Formatear fecha y detectar idioma": { "main": [ [ { "node": "Unir datos", "type": "main", "index": 1 } ] ] }, "Obtener fechas e instructores": { "main": [ [ { "node": "Unir datos", "type": "main", "index": 0 } ] ] }, "Unir datos": { "main": [ [ { "node": "Edit Fields", "type": "main", "index": 0 } ] ] }, "Edit Fields": { "main": [ [ { "node": "Aggregate1", "type": "main", "index": 0 } ] ] }, "Schedule Trigger": { "main": [ [ { "node": "Obtener sesion1", "type": "main", "index": 0 } ] ] }, "Calcular sesion mas cercana4": { "main": [ [ { "node": "Obtener miembros", "type": "main", "index": 0 } ] ] }, "Obtener sesiones": { "main": [ [ { "node": "Calcular falta 48h o 24h1", "type": "main", "index": 0 } ] ] }, "Obtener coordinadores1": { "main": [ [ { "node": "Matchear coordinador y pais inscrito", "type": "main", "index": 0 } ] ] }, "Hay inscritos en la sesion?": { "main": [ [ { "node": "Obtener coordinadores1", "type": "main", "index": 0 } ], [] ] }, "Matchear coordinador y pais inscrito": { "main": [ [ { "node": "Obtener miembros RRHH Notificaciones", "type": "main", "index": 0 } ] ] }, "Hay inscritos?": { "main": [ [ { "node": "Es espanol o ingles1", "type": "main", "index": 0 } ], [ { "node": "Es espanol o ingles", "type": "main", "index": 0 } ] ] }, "Registrar empleado a la sesion": { "main": [ [] ] }, "Registrar empleado a la sesion1": { "main": [ [] ] }, "Registrar empleado a la sesion2": { "main": [ [ { "node": "Wait", "type": "main", "index": 0 } ] ] }, "Registrar empleado a la sesion3": { "main": [ [ { "node": "Wait", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol": { "main": [ [ { "node": "Cambiar zona horaria", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles": { "main": [ [ { "node": "Cambiar zona horaria1", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol1": { "main": [ [ { "node": "Cambiar zona horaria2", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles1": { "main": [ [ { "node": "Cambiar zona horaria3", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria": { "main": [ [ { "node": "Send a message espanol", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria1": { "main": [ [ { "node": "Send a message ingles", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria2": { "main": [ [ { "node": "Send a message espanol1", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria3": { "main": [ [ { "node": "Send a message ingles1", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria5": { "main": [ [ { "node": "Send a message ingles2", "type": "main", "index": 0 } ] ] }, "Cambiar zona horaria4": { "main": [ [ { "node": "Send a message espanol2", "type": "main", "index": 0 } ] ] }, "Obtener sesion": { "main": [ [ { "node": "Pais?2", "type": "main", "index": 0 } ] ] }, "Obtener sesion1": { "main": [ [ { "node": "Calcular sesion mas cercana4", "type": "main", "index": 0 } ] ] }, "Tiene correo y pais?": { "main": [ [ { "node": "Entra hoy?", "type": "main", "index": 0 } ], [ { "node": "Insertar a inscritos (inactivo)", "type": "main", "index": 0 } ] ] }, "Tiene correo y pais?1": { "main": [ [ { "node": "Entra hoy?1", "type": "main", "index": 0 } ], [ { "node": "Wait2", "type": "main", "index": 0 } ] ] }, "Send a message espanol": { "main": [ [ { "node": "Registrar empleado a la sesion", "type": "main", "index": 0 } ] ] }, "Send a message ingles": { "main": [ [ { "node": "Registrar empleado a la sesion1", "type": "main", "index": 0 } ] ] }, "Actualizar datos del empleado y sesion asignada": { "main": [ [ { "node": "Convertir fecha a espanol1", "type": "main", "index": 0 } ] ] }, "Actualizar datos del empleado y sesion asignada1": { "main": [ [ { "node": "Convertir fecha a ingles1", "type": "main", "index": 0 } ] ] }, "Alerta no hay coordinador RRHH": { "main": [ [ { "node": "Pais?", "type": "main", "index": 0 } ] ] }, "Obtener conferenceRecord": { "main": [ [ { "node": "Buscar sesion con hora UTC", "type": "main", "index": 0 } ] ] }, "Limpiar id": { "main": [ [ { "node": "Get a contact", "type": "main", "index": 0 } ] ] }, "Get a contact": { "main": [ [ { "node": "Unir datos2", "type": "main", "index": 0 } ] ] }, "Unir datos2": { "main": [ [ { "node": "Hay inscritos?", "type": "main", "index": 0 } ] ] }, "Obtener miembros": { "main": [ [ { "node": "Limpiar id", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Es espanol o ingles1": { "main": [ [ { "node": "Formatear datos ingles", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol", "type": "main", "index": 0 } ] ] }, "Es espanol o ingles": { "main": [ [ { "node": "Formatear datos ingles1", "type": "main", "index": 0 } ], [ { "node": "Formatear datos espanol1", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles1": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol1": { "main": [ [ { "node": "Enviar notifacion a glmway notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos ingles2": { "main": [ [ { "node": "Enviar notificacion a rrhh notificaciones", "type": "main", "index": 0 } ] ] }, "Formatear datos espanol2": { "main": [ [ { "node": "Enviar notificacion a rrhh notificaciones1", "type": "main", "index": 0 } ] ] }, "Calcular falta 48h o 24h1": { "main": [ [ { "node": "Hay inscritos en la sesion?", "type": "main", "index": 0 } ] ] }, "Get a contact1": { "main": [ [ { "node": "Unir datos3", "type": "main", "index": 0 } ] ] }, "Limpiar id1": { "main": [ [ { "node": "Get a contact1", "type": "main", "index": 0 } ] ] }, "Unir datos3": { "main": [ [ { "node": "Pais?3", "type": "main", "index": 0 } ] ] }, "Obtener miembros RRHH Notificaciones": { "main": [ [ { "node": "Limpiar id1", "type": "main", "index": 0 } ] ] }, "Obtener coordinador3": { "main": [ [ { "node": "Hay coordinador?", "type": "main", "index": 0 } ] ] }, "Obtener coordinador4": { "main": [ [ { "node": "Hay coordinador?1", "type": "main", "index": 0 } ] ] }, "Obtener sesion2": { "main": [ [ { "node": "Buscar participantes", "type": "main", "index": 0 }, { "node": "Actualizar instructor de inscritos", "type": "main", "index": 0 } ] ] }, "Obtener participantes": { "main": [ [ { "node": "Detectar participantes en la sesion", "type": "main", "index": 0 } ] ] }, "Buscar participantes": { "main": [ [ { "node": "Split Out", "type": "main", "index": 0 } ] ] }, "Split Out": { "main": [ [ { "node": "Actualizar asistencia", "type": "main", "index": 0 } ] ] }, "Schedule Trigger7": { "main": [ [ { "node": "Hora de la reunion", "type": "main", "index": 0 } ] ] }, "Detectar participantes en la sesion": { "main": [ [ { "node": "Obtener sesion2", "type": "main", "index": 0 } ] ] }, "Actualizar asistencia": { "main": [ [ { "node": "Asistio?", "type": "main", "index": 0 } ] ] }, "Pais?4": { "main": [ [ { "node": "Send a message ingles4", "type": "main", "index": 0 } ], [ { "node": "Send a message espanol4", "type": "main", "index": 0 } ] ] }, "Asistio?": { "main": [ [ { "node": "Cortar nombre", "type": "main", "index": 0 } ] ] }, "Cortar nombre": { "main": [ [ { "node": "Pais?4", "type": "main", "index": 0 } ] ] }, "Buscar sesion con hora UTC": { "main": [ [ { "node": "Obtener participantes", "type": "main", "index": 0 } ] ] }, "Webhook1": { "main": [ [ { "node": "Incrementar conteo de evaluaciones respondidas", "type": "main", "index": 0 } ] ] }, "Enviar notificacion a rrhh notificaciones": { "main": [ [] ] }, "Enviar notificacion a rrhh notificaciones1": { "main": [ [] ] }, "Obtener conferenceRecord1": { "main": [ [ { "node": "Split Out1", "type": "main", "index": 0 } ] ] }, "Composio - Obtener registro": { "main": [ [ { "node": "Composio - Obtener participantes", "type": "main", "index": 0 } ] ] }, "Convertir fecha a espanol2": { "main": [ [ { "node": "Cambiar zona horaria4", "type": "main", "index": 0 } ] ] }, "Convertir fecha a ingles2": { "main": [ [ { "node": "Cambiar zona horaria5", "type": "main", "index": 0 } ] ] }, "Split Out1": { "main": [ [ { "node": "Aggregate2", "type": "main", "index": 0 } ] ] }, "Aggregate2": { "main": [ [ { "node": "Obtener participantes1", "type": "main", "index": 0 } ] ] }, "Hora de la reunion": { "main": [ [ { "node": "Obtener conferenceRecord", "type": "main", "index": 0 } ] ] }, "Obtener participantes1": { "main": [ [] ] }, "Actualizar estado a evaluacion_enviada": { "main": [ [ { "node": "Incrementar conteo de evaluaciones enviadas", "type": "main", "index": 0 } ] ] } }, "authors": "Eidan Then", "name": "Version f657df3d", "description": "", "autosaved": true, "workflowPublishHistory": [ { "createdAt": "2026-08-27T17:54:10.299Z", "id": 5262, "workflowId": "F1iPg8hktNAebZua", "versionId": "f657df3d-e5b6-445e-ad75-df66da81ebf3", "event": "activated", "userId": "de14e7e5-491b-4983-abb2-f88af42e92fd" } ] } } }