{ "updatedAt": "2026-08-01T13:39:03.486Z", "createdAt": "2026-07-29T18:42:21.837Z", "id": "4ysmdoCtcyBHB0pW", "name": "Seguimiento de Impuestos GLM - Google Calendar", "description": null, "active": true, "isArchived": false, "nodes": [ { "parameters": { "httpMethod": "POST", "path": "seguimiento-impuestos-google-calendar", "responseMode": "responseNode", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -1648, 432 ], "id": "c1faefdb-cec7-4565-9397-f2ff1487dfba", "name": "Webhook - Google Calendar", "webhookId": "seguimiento-impuestos-google-calendar" }, { "parameters": { "jsCode": "let body = $json.body ?? $json;\nif (typeof body === 'string') {\n try { body = JSON.parse(body); }\n catch { body = {}; }\n}\nconst action = String(body.action ?? '').trim().toLowerCase();\nconst payload = body.payload ?? {};\nconst obligationId = String(payload.obligation_id ?? body.obligation_id ?? '').trim();\nconst allowed = ['obligation.created', 'obligation.updated', 'obligation.deleted'];\nreturn [{\n json: {\n valid: allowed.includes(action) && Boolean(obligationId),\n action,\n obligation_id: obligationId,\n message: allowed.includes(action)\n ? (obligationId ? '' : 'Falta obligation_id.')\n : 'Acción no soportada.',\n },\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1408, 432 ], "id": "a052bc4b-6571-4105-8d41-634152a727b9", "name": "Preparar solicitud" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "771f008a-734d-436d-9122-448758a2263a", "leftValue": "={{ $json.valid }}", "rightValue": true, "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ -1168, 432 ], "id": "8b860c5e-b8f6-4d90-9829-a192c5bd807e", "name": "Solicitud válida" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_google_calendar_payload", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $json.obligation_id } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -912, 336 ], "id": "b20b6a2b-6ec1-4e6c-a8eb-5d10404ab80e", "name": "Supabase - Obtener obligación y asistentes" }, { "parameters": { "jsCode": "const source = $('Preparar solicitud').item.json;\nconst value = $json;\n\nconst row = Array.isArray(value)\n ? value[0]\n : Array.isArray(value?.data)\n ? value.data[0]\n : value;\n\nif (!row?.obligation_id) {\n return [\n {\n json: {\n ...source,\n operation: 'noop',\n reason: 'No se encontró la obligación.',\n },\n },\n ];\n}\n\nconst formatDateDMY = (value) => {\n const iso = String(value ?? '').trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(iso);\n\n if (!match) {\n return iso;\n }\n\n const [, year, month, day] = match;\n return `${day}-${month}-${year}`;\n};\n\nconst attendees = Array.isArray(row.attendees)\n ? [\n ...new Set(\n row.attendees\n .map((email) => String(email ?? '').trim().toLowerCase())\n .filter(Boolean),\n ),\n ]\n : [];\n\nconst start = `${row.due_date}T08:00:00-04:00`;\nconst end = `${row.due_date}T09:00:00-04:00`;\n\nconst categoryLabel =\n row.category === 'nomina'\n ? 'Nómina'\n : 'Administración';\n\nconst summary =\n `Impuestos · ${row.country_name} · ${row.description}`;\n\nconst description = [\n 'Seguimiento de Impuestos GLM',\n '',\n `País: ${row.country_name}`,\n `Categoría: ${categoryLabel}`,\n `Fecha límite: ${formatDateDMY(row.due_date)}`,\n `Obligación: ${row.description}`,\n '',\n 'Abrir aplicación: https://digitalcompass.agency/calendario-impuestos/',\n].join('\\n');\n\nconst calendarBody = {\n summary,\n description,\n\n start: {\n dateTime: start,\n timeZone: 'America/Santo_Domingo',\n },\n\n end: {\n dateTime: end,\n timeZone: 'America/Santo_Domingo',\n },\n\n attendees: attendees.map((email) => ({\n email,\n })),\n\n reminders: {\n useDefault: false,\n overrides: [\n {\n method: 'email',\n minutes: 0,\n },\n {\n method: 'popup',\n minutes: 0,\n },\n ],\n },\n\n extendedProperties: {\n private: {\n glmTaxObligationId: row.obligation_id,\n glmTaxCountryCode: row.country_code,\n glmTaxCategory: row.category,\n },\n },\n};\n\nlet operation = 'create';\n\nif (\n source.action === 'obligation.deleted' ||\n row.active === false\n) {\n operation = row.google_event_id\n ? 'delete'\n : 'noop';\n} else if (row.google_event_id) {\n operation = 'update';\n}\n\nreturn [\n {\n json: {\n ...source,\n ...row,\n attendees,\n start,\n end,\n summary,\n calendar_description: description,\n calendar_body: calendarBody,\n calendar_id: row.calendar_id || 'primary',\n operation,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -656, 336 ], "id": "86e2c9f1-46cb-42b0-83a2-43d420b6a85f", "name": "Preparar payload Calendar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'create');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 208 ], "id": "2d6990ec-a638-463b-8364-7d6a77b9bb9b", "name": "Preparar crear" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'update');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 368 ], "id": "868962b2-1894-41e4-9028-598b96a9ccc1", "name": "Preparar actualizar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'delete');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 528 ], "id": "57b9d7e3-084a-4d95-8ba2-309b83a71551", "name": "Preparar eliminar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'noop');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 688 ], "id": "8ffaf543-58e2-45c6-bcd3-0e56d9c18bc7", "name": "Preparar sin acción" }, { "parameters": { "method": "POST", "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json.calendar_body }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 208 ], "id": "6a998d06-8660-4b98-9f5b-58af9d92bda1", "name": "Google Calendar - Crear evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "method": "PATCH", "url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/primary/events/' + encodeURIComponent($json.google_event_id) + '?sendUpdates=all' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json.calendar_body }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 368 ], "id": "7831e93c-af0a-4505-80c0-c9707d5abff0", "name": "Google Calendar - Actualizar evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "method": "DELETE", "url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/primary/events/' + encodeURIComponent($json.google_event_id) + '?sendUpdates=all' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 528 ], "id": "d43bb286-0ce0-4e44-a9d9-5be15e325877", "name": "Google Calendar - Eliminar evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "jsCode": "const source = $('Preparar crear').item.json; return [{ json: { ...source, google_event_id: String($json.id ?? ''), google_response: $json, sync_action: 'create', sync_status: 'active' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 208 ], "id": "3bc4fa25-5ab2-4f01-a36f-bb3ab678cff7", "name": "Preparar registro creado" }, { "parameters": { "jsCode": "const source = $('Preparar actualizar').item.json; return [{ json: { ...source, google_event_id: source.google_event_id, google_response: $json, sync_action: 'update', sync_status: 'active' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 368 ], "id": "19961094-0e2b-4b63-8afe-5996a8fe2d46", "name": "Preparar registro actualizado" }, { "parameters": { "jsCode": "const source = $('Preparar eliminar').item.json; return [{ json: { ...source, google_event_id: source.google_event_id, google_response: $json ?? {}, sync_action: 'delete', sync_status: 'deleted' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 528 ], "id": "2108e3aa-935b-4fa3-ad66-1ddce0676212", "name": "Preparar registro eliminado" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro creado').item.json.obligation_id, p_google_event_id: $('Preparar registro creado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro creado').item.json.attendees, p_status: $('Preparar registro creado').item.json.sync_status, p_last_action: $('Preparar registro creado').item.json.sync_action, p_provider_response: $('Preparar registro creado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 208 ], "id": "bf61e834-6dd9-4838-b74a-927839a91ddc", "name": "Supabase - Registrar creación Calendar" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro actualizado').item.json.obligation_id, p_google_event_id: $('Preparar registro actualizado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro actualizado').item.json.attendees, p_status: $('Preparar registro actualizado').item.json.sync_status, p_last_action: $('Preparar registro actualizado').item.json.sync_action, p_provider_response: $('Preparar registro actualizado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 368 ], "id": "78bda986-5713-427a-8852-d791dbc8a1cc", "name": "Supabase - Registrar actualización Calendar" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro eliminado').item.json.obligation_id, p_google_event_id: $('Preparar registro eliminado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro eliminado').item.json.attendees, p_status: $('Preparar registro eliminado').item.json.sync_status, p_last_action: $('Preparar registro eliminado').item.json.sync_action, p_provider_response: $('Preparar registro eliminado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 528 ], "id": "b05991ba-18fa-498a-a52e-f3b4bf296793", "name": "Supabase - Registrar eliminación Calendar" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento creado en Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 208 ], "id": "8237b91a-ec81-4e45-9641-9138e354febe", "name": "Responder creación" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento actualizado en Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 368 ], "id": "954c7fd8-82d7-4460-9e0e-53c5e1bb30be", "name": "Responder actualización" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento eliminado de Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 528 ], "id": "c4542b04-2b4e-49da-b189-ed6d4fda092d", "name": "Responder eliminación" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: $json.reason || 'No había cambios que sincronizar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ -144, 688 ], "id": "8a17b617-3311-47a9-9ac6-153894215600", "name": "Responder sin acción" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: false, message: $json.message } }}", "options": { "responseCode": 400, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ -912, 608 ], "id": "328640f6-5d22-46a0-89dc-46580ec2f6a8", "name": "Responder solicitud inválida" } ], "connections": { "Webhook - Google Calendar": { "main": [ [ { "node": "Preparar solicitud", "type": "main", "index": 0 } ] ] }, "Preparar solicitud": { "main": [ [ { "node": "Solicitud válida", "type": "main", "index": 0 } ] ] }, "Solicitud válida": { "main": [ [ { "node": "Supabase - Obtener obligación y asistentes", "type": "main", "index": 0 } ], [ { "node": "Responder solicitud inválida", "type": "main", "index": 0 } ] ] }, "Supabase - Obtener obligación y asistentes": { "main": [ [ { "node": "Preparar payload Calendar", "type": "main", "index": 0 } ] ] }, "Preparar payload Calendar": { "main": [ [ { "node": "Preparar crear", "type": "main", "index": 0 }, { "node": "Preparar actualizar", "type": "main", "index": 0 }, { "node": "Preparar eliminar", "type": "main", "index": 0 }, { "node": "Preparar sin acción", "type": "main", "index": 0 } ] ] }, "Preparar crear": { "main": [ [ { "node": "Google Calendar - Crear evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Crear evento": { "main": [ [ { "node": "Preparar registro creado", "type": "main", "index": 0 } ] ] }, "Preparar registro creado": { "main": [ [ { "node": "Supabase - Registrar creación Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar creación Calendar": { "main": [ [ { "node": "Responder creación", "type": "main", "index": 0 } ] ] }, "Preparar actualizar": { "main": [ [ { "node": "Google Calendar - Actualizar evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Actualizar evento": { "main": [ [ { "node": "Preparar registro actualizado", "type": "main", "index": 0 } ] ] }, "Preparar registro actualizado": { "main": [ [ { "node": "Supabase - Registrar actualización Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar actualización Calendar": { "main": [ [ { "node": "Responder actualización", "type": "main", "index": 0 } ] ] }, "Preparar eliminar": { "main": [ [ { "node": "Google Calendar - Eliminar evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Eliminar evento": { "main": [ [ { "node": "Preparar registro eliminado", "type": "main", "index": 0 } ] ] }, "Preparar registro eliminado": { "main": [ [ { "node": "Supabase - Registrar eliminación Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar eliminación Calendar": { "main": [ [ { "node": "Responder eliminación", "type": "main", "index": 0 } ] ] }, "Preparar sin acción": { "main": [ [ { "node": "Responder sin acción", "type": "main", "index": 0 } ] ] } }, "settings": { "executionOrder": "v1", "binaryMode": "separate" }, "staticData": null, "meta": null, "versionId": "2d288ae2-36eb-44a6-8ded-442efef8f8fe", "activeVersionId": "2d288ae2-36eb-44a6-8ded-442efef8f8fe", "versionCounter": 20, "triggerCount": 1, "shared": [ { "updatedAt": "2026-07-29T18:42:21.854Z", "createdAt": "2026-07-29T18:42:21.854Z", "role": "workflow:owner", "workflowId": "4ysmdoCtcyBHB0pW", "projectId": "PJpTANzTXIFibWsW", "project": { "updatedAt": "2026-04-22T14:25:09.686Z", "createdAt": "2026-04-22T14:22:54.790Z", "id": "PJpTANzTXIFibWsW", "name": "Isaac Aracena ", "type": "personal", "icon": null, "description": null, "creatorId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" } } ], "tags": [], "activeVersion": { "updatedAt": "2026-08-01T13:39:06.000Z", "createdAt": "2026-08-01T13:39:03.488Z", "versionId": "2d288ae2-36eb-44a6-8ded-442efef8f8fe", "workflowId": "4ysmdoCtcyBHB0pW", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "seguimiento-impuestos-google-calendar", "responseMode": "responseNode", "options": {} }, "type": "n8n-nodes-base.webhook", "typeVersion": 2.1, "position": [ -1648, 432 ], "id": "c1faefdb-cec7-4565-9397-f2ff1487dfba", "name": "Webhook - Google Calendar", "webhookId": "seguimiento-impuestos-google-calendar" }, { "parameters": { "jsCode": "let body = $json.body ?? $json;\nif (typeof body === 'string') {\n try { body = JSON.parse(body); }\n catch { body = {}; }\n}\nconst action = String(body.action ?? '').trim().toLowerCase();\nconst payload = body.payload ?? {};\nconst obligationId = String(payload.obligation_id ?? body.obligation_id ?? '').trim();\nconst allowed = ['obligation.created', 'obligation.updated', 'obligation.deleted'];\nreturn [{\n json: {\n valid: allowed.includes(action) && Boolean(obligationId),\n action,\n obligation_id: obligationId,\n message: allowed.includes(action)\n ? (obligationId ? '' : 'Falta obligation_id.')\n : 'Acción no soportada.',\n },\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -1408, 432 ], "id": "a052bc4b-6571-4105-8d41-634152a727b9", "name": "Preparar solicitud" }, { "parameters": { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 2 }, "conditions": [ { "id": "771f008a-734d-436d-9122-448758a2263a", "leftValue": "={{ $json.valid }}", "rightValue": true, "operator": { "type": "boolean", "operation": "true", "singleValue": true } } ], "combinator": "and" }, "options": {} }, "type": "n8n-nodes-base.if", "typeVersion": 2.2, "position": [ -1168, 432 ], "id": "8b860c5e-b8f6-4d90-9829-a192c5bd807e", "name": "Solicitud válida" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_google_calendar_payload", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $json.obligation_id } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -912, 336 ], "id": "b20b6a2b-6ec1-4e6c-a8eb-5d10404ab80e", "name": "Supabase - Obtener obligación y asistentes" }, { "parameters": { "jsCode": "const source = $('Preparar solicitud').item.json;\nconst value = $json;\n\nconst row = Array.isArray(value)\n ? value[0]\n : Array.isArray(value?.data)\n ? value.data[0]\n : value;\n\nif (!row?.obligation_id) {\n return [\n {\n json: {\n ...source,\n operation: 'noop',\n reason: 'No se encontró la obligación.',\n },\n },\n ];\n}\n\nconst formatDateDMY = (value) => {\n const iso = String(value ?? '').trim();\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(iso);\n\n if (!match) {\n return iso;\n }\n\n const [, year, month, day] = match;\n return `${day}-${month}-${year}`;\n};\n\nconst attendees = Array.isArray(row.attendees)\n ? [\n ...new Set(\n row.attendees\n .map((email) => String(email ?? '').trim().toLowerCase())\n .filter(Boolean),\n ),\n ]\n : [];\n\nconst start = `${row.due_date}T08:00:00-04:00`;\nconst end = `${row.due_date}T09:00:00-04:00`;\n\nconst categoryLabel =\n row.category === 'nomina'\n ? 'Nómina'\n : 'Administración';\n\nconst summary =\n `Impuestos · ${row.country_name} · ${row.description}`;\n\nconst description = [\n 'Seguimiento de Impuestos GLM',\n '',\n `País: ${row.country_name}`,\n `Categoría: ${categoryLabel}`,\n `Fecha límite: ${formatDateDMY(row.due_date)}`,\n `Obligación: ${row.description}`,\n '',\n 'Abrir aplicación: https://digitalcompass.agency/calendario-impuestos/',\n].join('\\n');\n\nconst calendarBody = {\n summary,\n description,\n\n start: {\n dateTime: start,\n timeZone: 'America/Santo_Domingo',\n },\n\n end: {\n dateTime: end,\n timeZone: 'America/Santo_Domingo',\n },\n\n attendees: attendees.map((email) => ({\n email,\n })),\n\n reminders: {\n useDefault: false,\n overrides: [\n {\n method: 'email',\n minutes: 0,\n },\n {\n method: 'popup',\n minutes: 0,\n },\n ],\n },\n\n extendedProperties: {\n private: {\n glmTaxObligationId: row.obligation_id,\n glmTaxCountryCode: row.country_code,\n glmTaxCategory: row.category,\n },\n },\n};\n\nlet operation = 'create';\n\nif (\n source.action === 'obligation.deleted' ||\n row.active === false\n) {\n operation = row.google_event_id\n ? 'delete'\n : 'noop';\n} else if (row.google_event_id) {\n operation = 'update';\n}\n\nreturn [\n {\n json: {\n ...source,\n ...row,\n attendees,\n start,\n end,\n summary,\n calendar_description: description,\n calendar_body: calendarBody,\n calendar_id: row.calendar_id || 'primary',\n operation,\n },\n },\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -656, 336 ], "id": "86e2c9f1-46cb-42b0-83a2-43d420b6a85f", "name": "Preparar payload Calendar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'create');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 208 ], "id": "2d6990ec-a638-463b-8364-7d6a77b9bb9b", "name": "Preparar crear" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'update');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 368 ], "id": "868962b2-1894-41e4-9028-598b96a9ccc1", "name": "Preparar actualizar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'delete');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 528 ], "id": "57b9d7e3-084a-4d95-8ba2-309b83a71551", "name": "Preparar eliminar" }, { "parameters": { "jsCode": "return $input.all().filter((item) => item.json.operation === 'noop');" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ -400, 688 ], "id": "8ffaf543-58e2-45c6-bcd3-0e56d9c18bc7", "name": "Preparar sin acción" }, { "parameters": { "method": "POST", "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json.calendar_body }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 208 ], "id": "6a998d06-8660-4b98-9f5b-58af9d92bda1", "name": "Google Calendar - Crear evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "method": "PATCH", "url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/primary/events/' + encodeURIComponent($json.google_event_id) + '?sendUpdates=all' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ $json.calendar_body }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 368 ], "id": "7831e93c-af0a-4505-80c0-c9707d5abff0", "name": "Google Calendar - Actualizar evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "method": "DELETE", "url": "={{ 'https://www.googleapis.com/calendar/v3/calendars/primary/events/' + encodeURIComponent($json.google_event_id) + '?sendUpdates=all' }}", "authentication": "predefinedCredentialType", "nodeCredentialType": "googleCalendarOAuth2Api", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ -144, 528 ], "id": "d43bb286-0ce0-4e44-a9d9-5be15e325877", "name": "Google Calendar - Eliminar evento", "credentials": { "googleCalendarOAuth2Api": { "id": "QabWebE9XbAY72tU", "name": "Google Calendar account" } } }, { "parameters": { "jsCode": "const source = $('Preparar crear').item.json; return [{ json: { ...source, google_event_id: String($json.id ?? ''), google_response: $json, sync_action: 'create', sync_status: 'active' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 208 ], "id": "3bc4fa25-5ab2-4f01-a36f-bb3ab678cff7", "name": "Preparar registro creado" }, { "parameters": { "jsCode": "const source = $('Preparar actualizar').item.json; return [{ json: { ...source, google_event_id: source.google_event_id, google_response: $json, sync_action: 'update', sync_status: 'active' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 368 ], "id": "19961094-0e2b-4b63-8afe-5996a8fe2d46", "name": "Preparar registro actualizado" }, { "parameters": { "jsCode": "const source = $('Preparar eliminar').item.json; return [{ json: { ...source, google_event_id: source.google_event_id, google_response: $json ?? {}, sync_action: 'delete', sync_status: 'deleted' } }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 112, 528 ], "id": "2108e3aa-935b-4fa3-ad66-1ddce0676212", "name": "Preparar registro eliminado" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro creado').item.json.obligation_id, p_google_event_id: $('Preparar registro creado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro creado').item.json.attendees, p_status: $('Preparar registro creado').item.json.sync_status, p_last_action: $('Preparar registro creado').item.json.sync_action, p_provider_response: $('Preparar registro creado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 208 ], "id": "bf61e834-6dd9-4838-b74a-927839a91ddc", "name": "Supabase - Registrar creación Calendar" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro actualizado').item.json.obligation_id, p_google_event_id: $('Preparar registro actualizado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro actualizado').item.json.attendees, p_status: $('Preparar registro actualizado').item.json.sync_status, p_last_action: $('Preparar registro actualizado').item.json.sync_action, p_provider_response: $('Preparar registro actualizado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 368 ], "id": "78bda986-5713-427a-8852-d791dbc8a1cc", "name": "Supabase - Registrar actualización Calendar" }, { "parameters": { "method": "POST", "url": "https://dbit.digitalcompass.agency/rest/v1/rpc/tax_record_google_calendar_sync", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "apikey", "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Authorization", "value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={{ { p_obligation_id: $('Preparar registro eliminado').item.json.obligation_id, p_google_event_id: $('Preparar registro eliminado').item.json.google_event_id, p_calendar_id: 'primary', p_attendees: $('Preparar registro eliminado').item.json.attendees, p_status: $('Preparar registro eliminado').item.json.sync_status, p_last_action: $('Preparar registro eliminado').item.json.sync_action, p_provider_response: $('Preparar registro eliminado').item.json.google_response } }}", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [ 368, 528 ], "id": "b05991ba-18fa-498a-a52e-f3b4bf296793", "name": "Supabase - Registrar eliminación Calendar" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento creado en Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 208 ], "id": "8237b91a-ec81-4e45-9641-9138e354febe", "name": "Responder creación" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento actualizado en Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 368 ], "id": "954c7fd8-82d7-4460-9e0e-53c5e1bb30be", "name": "Responder actualización" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: 'Evento eliminado de Google Calendar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" }, { "name": "Cache-Control", "value": "no-store" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ 624, 528 ], "id": "c4542b04-2b4e-49da-b189-ed6d4fda092d", "name": "Responder eliminación" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: true, message: $json.reason || 'No había cambios que sincronizar.' } }}", "options": { "responseCode": 200, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ -144, 688 ], "id": "8a17b617-3311-47a9-9ac6-153894215600", "name": "Responder sin acción" }, { "parameters": { "respondWith": "json", "responseBody": "={{ { ok: false, message: $json.message } }}", "options": { "responseCode": 400, "responseHeaders": { "entries": [ { "name": "Access-Control-Allow-Origin", "value": "*" } ] } } }, "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1.4, "position": [ -912, 608 ], "id": "328640f6-5d22-46a0-89dc-46580ec2f6a8", "name": "Responder solicitud inválida" } ], "connections": { "Webhook - Google Calendar": { "main": [ [ { "node": "Preparar solicitud", "type": "main", "index": 0 } ] ] }, "Preparar solicitud": { "main": [ [ { "node": "Solicitud válida", "type": "main", "index": 0 } ] ] }, "Solicitud válida": { "main": [ [ { "node": "Supabase - Obtener obligación y asistentes", "type": "main", "index": 0 } ], [ { "node": "Responder solicitud inválida", "type": "main", "index": 0 } ] ] }, "Supabase - Obtener obligación y asistentes": { "main": [ [ { "node": "Preparar payload Calendar", "type": "main", "index": 0 } ] ] }, "Preparar payload Calendar": { "main": [ [ { "node": "Preparar crear", "type": "main", "index": 0 }, { "node": "Preparar actualizar", "type": "main", "index": 0 }, { "node": "Preparar eliminar", "type": "main", "index": 0 }, { "node": "Preparar sin acción", "type": "main", "index": 0 } ] ] }, "Preparar crear": { "main": [ [ { "node": "Google Calendar - Crear evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Crear evento": { "main": [ [ { "node": "Preparar registro creado", "type": "main", "index": 0 } ] ] }, "Preparar registro creado": { "main": [ [ { "node": "Supabase - Registrar creación Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar creación Calendar": { "main": [ [ { "node": "Responder creación", "type": "main", "index": 0 } ] ] }, "Preparar actualizar": { "main": [ [ { "node": "Google Calendar - Actualizar evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Actualizar evento": { "main": [ [ { "node": "Preparar registro actualizado", "type": "main", "index": 0 } ] ] }, "Preparar registro actualizado": { "main": [ [ { "node": "Supabase - Registrar actualización Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar actualización Calendar": { "main": [ [ { "node": "Responder actualización", "type": "main", "index": 0 } ] ] }, "Preparar eliminar": { "main": [ [ { "node": "Google Calendar - Eliminar evento", "type": "main", "index": 0 } ] ] }, "Google Calendar - Eliminar evento": { "main": [ [ { "node": "Preparar registro eliminado", "type": "main", "index": 0 } ] ] }, "Preparar registro eliminado": { "main": [ [ { "node": "Supabase - Registrar eliminación Calendar", "type": "main", "index": 0 } ] ] }, "Supabase - Registrar eliminación Calendar": { "main": [ [ { "node": "Responder eliminación", "type": "main", "index": 0 } ] ] }, "Preparar sin acción": { "main": [ [ { "node": "Responder sin acción", "type": "main", "index": 0 } ] ] } }, "authors": "Isaac Aracena", "name": "Version 2d288ae2", "description": "", "autosaved": true, "workflowPublishHistory": [ { "createdAt": "2026-08-01T13:39:06.820Z", "id": 3817, "workflowId": "4ysmdoCtcyBHB0pW", "versionId": "2d288ae2-36eb-44a6-8ded-442efef8f8fe", "event": "activated", "userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029" } ] } }