Update backup: Portal de Verificación de Nómina - Reportar corrección BambooHR a RRHH
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"updatedAt": "2026-08-11T18:48:49.761Z",
|
||||
"updatedAt": "2026-08-19T14:20:00.099Z",
|
||||
"createdAt": "2026-08-11T18:47:42.698Z",
|
||||
"id": "0yaiagL1tWdhRUXy",
|
||||
"name": "Portal de Verificación de Nómina - Reportar corrección BambooHR a RRHH",
|
||||
@@ -17,10 +17,10 @@
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
0,
|
||||
0
|
||||
256,
|
||||
528
|
||||
],
|
||||
"id": "7e321136-0268-4f7e-bde1-b3a7b1b60caf",
|
||||
"id": "9f82287d-3017-4fb8-be43-3c3313f4e466",
|
||||
"name": "Webhook",
|
||||
"webhookId": "df5cb56b-75f3-4e8b-a1f2-f9a05c8ec317"
|
||||
},
|
||||
@@ -31,10 +31,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
240,
|
||||
0
|
||||
496,
|
||||
528
|
||||
],
|
||||
"id": "507c0065-11d8-4693-86d7-acaaf826d8a0",
|
||||
"id": "48884cdb-c052-4e9c-ac95-1d0eac8911f3",
|
||||
"name": "Preparar solicitud"
|
||||
},
|
||||
{
|
||||
@@ -68,10 +68,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
480,
|
||||
0
|
||||
736,
|
||||
528
|
||||
],
|
||||
"id": "9b9f3800-4182-4cc4-a6e3-11e200c44b1f",
|
||||
"id": "3b5acfa4-19f9-41cf-943b-2dddf799b909",
|
||||
"name": "Validar acceso Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -84,10 +84,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
720,
|
||||
0
|
||||
976,
|
||||
528
|
||||
],
|
||||
"id": "b20cb8fa-fa37-48a5-93aa-dd1740e8a6c0",
|
||||
"id": "23a5aabe-20be-4f4d-92a2-e4d400b96d75",
|
||||
"name": "Validar usuario"
|
||||
},
|
||||
{
|
||||
@@ -131,10 +131,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
960,
|
||||
0
|
||||
1216,
|
||||
528
|
||||
],
|
||||
"id": "5dc107fa-c704-4643-9479-1f57e163d5fd",
|
||||
"id": "07be5909-2a5b-47f4-96b2-466f2658f0db",
|
||||
"name": "Consultar empleado BambooHR",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 3,
|
||||
@@ -148,15 +148,15 @@
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const request = $('Validar usuario').first().json || {};\nconst raw = $input.first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction normalizeName(value) {\n return clean(value)\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9 ]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction normalizeIdentifier(value) {\n return clean(value).toUpperCase().replace(/[^A-Z0-9]/g, '');\n}\n\nfunction countryMatches(employee) {\n const location = normalizeName(\n employee.location ||\n employee.jobInformationLocation ||\n employee.jobLocation ||\n employee.country ||\n ''\n );\n\n if (request.country === 'GT') {\n return location.includes('guatemala');\n }\n\n return location.includes('trinidad') || location.includes('tobago');\n}\n\nfunction employeeAliases(employee) {\n const first = clean(employee.firstName || employee.first_name);\n const middle = clean(employee.middleName || employee.middle_name);\n const last = clean(employee.lastName || employee.last_name);\n const display = clean(employee.displayName || employee.fullName || employee.full_name);\n\n return Array.from(new Set([\n display,\n [first, middle, last].filter(Boolean).join(' '),\n [first, last].filter(Boolean).join(' '),\n ].map(clean).filter(Boolean)));\n}\n\nconst employees = Array.isArray(raw.employees)\n ? raw.employees\n : Array.isArray(raw.data?.employees)\n ? raw.data.employees\n : [];\n\nif (!employees.length) {\n throw new Error('BambooHR no devolvió empleados para validar la corrección.');\n}\n\nconst candidates = employees.filter(countryMatches);\nif (!candidates.length) {\n throw new Error(`No se encontraron empleados de ${request.countryName} en BambooHR.`);\n}\n\nconst requestedNumber = normalizeIdentifier(request.bambooEmployeeNumber);\nlet matches = [];\nlet matchedBy = '';\n\nif (requestedNumber) {\n matches = candidates.filter((employee) =>\n normalizeIdentifier(employee.employeeNumber || employee.employee_number) === requestedNumber\n );\n matchedBy = 'employee_number';\n}\n\nif (!matches.length) {\n const targetName = normalizeName(request.bambooName);\n matches = candidates.filter((employee) =>\n employeeAliases(employee).some((alias) => normalizeName(alias) === targetName)\n );\n matchedBy = 'exact_bamboo_name';\n}\n\nif (matches.length !== 1) {\n if (matches.length > 1) {\n throw new Error('La identificación en BambooHR es ambigua. Indica el Employee Number para seleccionar una sola persona.');\n }\n\n throw new Error(\n 'No se encontró exactamente ese empleado en BambooHR para el país seleccionado. Revisa el nombre o indica el Employee Number.'\n );\n}\n\nconst employee = matches[0];\nconst aliases = employeeAliases(employee);\nconst actualName = clean(employee.displayName) || aliases[0] || request.bambooName;\nconst actualEmployeeNumber = clean(employee.employeeNumber || employee.employee_number);\nconst bambooId = clean(employee.employeeId || employee.id);\nconst now = new Date().toISOString();\n\nconst recipients = request.country === 'TT'\n ? ['lnicomejack@gomezleemarketing.com']\n : [\n 'pgamboa@gomezleemarketing.com',\n 'smeyer@gomezleemarketing.com',\n 'mjmorales@gomezleemarketing.com',\n ];\n\nconst aliasPayload = request.sourceNames.map((sourceName) => ({\n pais: request.country,\n nombre_origen: sourceName,\n nombre_origen_normalizado: normalizeName(sourceName),\n cuenta_bancaria: String(request.bankAccount || '').replace(/[^0-9A-Za-z]+/g, ''),\n bamboo_employee_number: actualEmployeeNumber || null,\n bamboo_employee_id: bambooId || null,\n bamboo_nombre: actualName,\n motivo: request.reason,\n comentario: request.comment || null,\n activo: true,\n validado_por_email: request.requestedByEmail,\n validado_por_nombre: request.requestedByName,\n last_reported_at: now,\n updated_at: now,\n}));\n\nreturn [{\n json: {\n request,\n matchedBy,\n employee: {\n bambooId,\n employeeNumber: actualEmployeeNumber,\n name: actualName,\n status: clean(employee.status),\n location: clean(employee.location),\n },\n recipients,\n aliasPayload,\n },\n}];"
|
||||
"jsCode": "const request = $('Validar usuario').first().json || {};\nconst raw = $input.first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction normalizeName(value) {\n return clean(value)\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9 ]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction normalizeIdentifier(value) {\n return clean(value).toUpperCase().replace(/[^A-Z0-9]/g, '');\n}\n\nfunction countryMatches(employee) {\n const location = normalizeName(\n employee.location ||\n employee.jobInformationLocation ||\n employee.jobLocation ||\n employee.country ||\n ''\n );\n\n if (request.country === 'GT') {\n return location.includes('guatemala');\n }\n\n return location.includes('trinidad') || location.includes('tobago');\n}\n\nfunction employeeAliases(employee) {\n const first = clean(employee.firstName || employee.first_name);\n const middle = clean(employee.middleName || employee.middle_name);\n const last = clean(employee.lastName || employee.last_name);\n const display = clean(employee.displayName || employee.fullName || employee.full_name);\n\n return Array.from(new Set([\n display,\n [first, middle, last].filter(Boolean).join(' '),\n [first, last].filter(Boolean).join(' '),\n ].map(clean).filter(Boolean)));\n}\n\nconst employees = Array.isArray(raw.employees)\n ? raw.employees\n : Array.isArray(raw.data?.employees)\n ? raw.data.employees\n : [];\n\nif (!employees.length) {\n throw new Error('BambooHR no devolvió empleados para validar la corrección.');\n}\n\nconst candidates = employees.filter(countryMatches);\nif (!candidates.length) {\n throw new Error(`No se encontraron empleados de ${request.countryName} en BambooHR.`);\n}\n\nconst requestedNumber = normalizeIdentifier(request.bambooEmployeeNumber);\nlet matches = [];\nlet matchedBy = '';\n\nif (requestedNumber) {\n matches = candidates.filter((employee) =>\n normalizeIdentifier(employee.employeeNumber || employee.employee_number) === requestedNumber\n );\n matchedBy = 'employee_number';\n}\n\nif (!matches.length) {\n const targetName = normalizeName(request.bambooName);\n matches = candidates.filter((employee) =>\n employeeAliases(employee).some((alias) => normalizeName(alias) === targetName)\n );\n matchedBy = 'exact_bamboo_name';\n}\n\nif (matches.length !== 1) {\n if (matches.length > 1) {\n throw new Error('La identificación en BambooHR es ambigua. Indica el Employee Number para seleccionar una sola persona.');\n }\n\n throw new Error(\n 'No se encontró exactamente ese empleado en BambooHR para el país seleccionado. Revisa el nombre o indica el Employee Number.'\n );\n}\n\nconst employee = matches[0];\nconst aliases = employeeAliases(employee);\nconst actualName = clean(employee.displayName) || aliases[0] || request.bambooName;\nconst actualEmployeeNumber = clean(employee.employeeNumber || employee.employee_number);\nconst bambooId = clean(employee.employeeId || employee.id);\nconst now = new Date().toISOString();\n\nconst recipients = request.country === 'TT'\n ? ['lnicomejack@gomezleemarketing.com']\n : ['haguirre@gomezleemarketing.com'];\n\nconst aliasPayload = request.sourceNames.map((sourceName) => ({\n pais: request.country,\n nombre_origen: sourceName,\n nombre_origen_normalizado: normalizeName(sourceName),\n cuenta_bancaria: String(request.bankAccount || '').replace(/[^0-9A-Za-z]+/g, ''),\n bamboo_employee_number: actualEmployeeNumber || null,\n bamboo_employee_id: bambooId || null,\n bamboo_nombre: actualName,\n motivo: request.reason,\n comentario: request.comment || null,\n activo: true,\n validado_por_email: request.requestedByEmail,\n validado_por_nombre: request.requestedByName,\n last_reported_at: now,\n updated_at: now,\n}));\n\nreturn [{\n json: {\n request,\n matchedBy,\n employee: {\n bambooId,\n employeeNumber: actualEmployeeNumber,\n name: actualName,\n status: clean(employee.status),\n location: clean(employee.location),\n },\n recipients,\n aliasPayload,\n },\n}];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1200,
|
||||
0
|
||||
1456,
|
||||
528
|
||||
],
|
||||
"id": "504eed05-c6be-442e-9707-8cd4aca1d19c",
|
||||
"id": "bb82de3a-cbbf-479c-a2da-96b677cb6eda",
|
||||
"name": "Resolver empleado BambooHR"
|
||||
},
|
||||
{
|
||||
@@ -194,10 +194,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
1440,
|
||||
0
|
||||
1696,
|
||||
528
|
||||
],
|
||||
"id": "6fc69ac2-6999-4810-9e8d-675c4c4d40ac",
|
||||
"id": "062d8846-d24a-4887-9ef3-7de4a5d204d4",
|
||||
"name": "Guardar alias Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -210,10 +210,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1680,
|
||||
0
|
||||
1936,
|
||||
528
|
||||
],
|
||||
"id": "9d565bf5-a6df-4ac9-bad1-abe48a277c37",
|
||||
"id": "3c1d6a0d-c096-4b31-9ba9-4ce2ec357f8e",
|
||||
"name": "Preparar auditoría"
|
||||
},
|
||||
{
|
||||
@@ -251,10 +251,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
1920,
|
||||
0
|
||||
2176,
|
||||
528
|
||||
],
|
||||
"id": "45f87d7b-a746-4eb2-a54e-d2de7645f854",
|
||||
"id": "9cd76301-127f-449a-a8c5-1bcdfe79de9a",
|
||||
"name": "Guardar solicitud Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -267,10 +267,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2160,
|
||||
0
|
||||
2416,
|
||||
528
|
||||
],
|
||||
"id": "68be3c1d-42eb-4bc5-aa35-36333261f2a6",
|
||||
"id": "6f05bfa0-78b5-4447-a440-19f90c6f7bba",
|
||||
"name": "Preparar correo RRHH"
|
||||
},
|
||||
{
|
||||
@@ -285,10 +285,10 @@
|
||||
"type": "n8n-nodes-base.gmail",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
2400,
|
||||
0
|
||||
2656,
|
||||
528
|
||||
],
|
||||
"id": "28f7c657-0c5b-47c6-898b-f68f1cf21378",
|
||||
"id": "9822f786-4c81-4a07-94ed-081e8485cbba",
|
||||
"name": "Enviar correo RRHH",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 3,
|
||||
@@ -336,10 +336,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
2640,
|
||||
0
|
||||
2896,
|
||||
528
|
||||
],
|
||||
"id": "87b7910e-0465-40b1-89d4-6b160726b7f7",
|
||||
"id": "3e801286-89a6-4e29-a443-4c1f5e5afe14",
|
||||
"name": "Marcar correo enviado",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -364,10 +364,10 @@
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.5,
|
||||
"position": [
|
||||
2880,
|
||||
0
|
||||
3136,
|
||||
528
|
||||
],
|
||||
"id": "1db48431-4661-49de-a495-66c740b2aac1",
|
||||
"id": "4359eea0-0f16-4241-840f-565d56700bb5",
|
||||
"name": "Respond to Webhook"
|
||||
}
|
||||
],
|
||||
@@ -511,9 +511,9 @@
|
||||
},
|
||||
"staticData": null,
|
||||
"meta": null,
|
||||
"versionId": "7e4daa40-244f-43ed-9d74-14a9cb589ddf",
|
||||
"activeVersionId": "7e4daa40-244f-43ed-9d74-14a9cb589ddf",
|
||||
"versionCounter": 5,
|
||||
"versionId": "a190ab40-7527-4805-a7ac-cc26ed1e558b",
|
||||
"activeVersionId": "a190ab40-7527-4805-a7ac-cc26ed1e558b",
|
||||
"versionCounter": 8,
|
||||
"triggerCount": 1,
|
||||
"shared": [
|
||||
{
|
||||
@@ -536,9 +536,9 @@
|
||||
],
|
||||
"tags": [],
|
||||
"activeVersion": {
|
||||
"updatedAt": "2026-08-11T18:47:55.000Z",
|
||||
"createdAt": "2026-08-11T18:47:42.715Z",
|
||||
"versionId": "7e4daa40-244f-43ed-9d74-14a9cb589ddf",
|
||||
"updatedAt": "2026-08-19T14:20:03.000Z",
|
||||
"createdAt": "2026-08-19T14:20:00.103Z",
|
||||
"versionId": "a190ab40-7527-4805-a7ac-cc26ed1e558b",
|
||||
"workflowId": "0yaiagL1tWdhRUXy",
|
||||
"nodes": [
|
||||
{
|
||||
@@ -551,10 +551,10 @@
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 2.1,
|
||||
"position": [
|
||||
0,
|
||||
0
|
||||
256,
|
||||
528
|
||||
],
|
||||
"id": "7e321136-0268-4f7e-bde1-b3a7b1b60caf",
|
||||
"id": "9f82287d-3017-4fb8-be43-3c3313f4e466",
|
||||
"name": "Webhook",
|
||||
"webhookId": "df5cb56b-75f3-4e8b-a1f2-f9a05c8ec317"
|
||||
},
|
||||
@@ -565,10 +565,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
240,
|
||||
0
|
||||
496,
|
||||
528
|
||||
],
|
||||
"id": "507c0065-11d8-4693-86d7-acaaf826d8a0",
|
||||
"id": "48884cdb-c052-4e9c-ac95-1d0eac8911f3",
|
||||
"name": "Preparar solicitud"
|
||||
},
|
||||
{
|
||||
@@ -602,10 +602,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
480,
|
||||
0
|
||||
736,
|
||||
528
|
||||
],
|
||||
"id": "9b9f3800-4182-4cc4-a6e3-11e200c44b1f",
|
||||
"id": "3b5acfa4-19f9-41cf-943b-2dddf799b909",
|
||||
"name": "Validar acceso Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -618,10 +618,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
720,
|
||||
0
|
||||
976,
|
||||
528
|
||||
],
|
||||
"id": "b20cb8fa-fa37-48a5-93aa-dd1740e8a6c0",
|
||||
"id": "23a5aabe-20be-4f4d-92a2-e4d400b96d75",
|
||||
"name": "Validar usuario"
|
||||
},
|
||||
{
|
||||
@@ -665,10 +665,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
960,
|
||||
0
|
||||
1216,
|
||||
528
|
||||
],
|
||||
"id": "5dc107fa-c704-4643-9479-1f57e163d5fd",
|
||||
"id": "07be5909-2a5b-47f4-96b2-466f2658f0db",
|
||||
"name": "Consultar empleado BambooHR",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 3,
|
||||
@@ -682,15 +682,15 @@
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"jsCode": "const request = $('Validar usuario').first().json || {};\nconst raw = $input.first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction normalizeName(value) {\n return clean(value)\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9 ]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction normalizeIdentifier(value) {\n return clean(value).toUpperCase().replace(/[^A-Z0-9]/g, '');\n}\n\nfunction countryMatches(employee) {\n const location = normalizeName(\n employee.location ||\n employee.jobInformationLocation ||\n employee.jobLocation ||\n employee.country ||\n ''\n );\n\n if (request.country === 'GT') {\n return location.includes('guatemala');\n }\n\n return location.includes('trinidad') || location.includes('tobago');\n}\n\nfunction employeeAliases(employee) {\n const first = clean(employee.firstName || employee.first_name);\n const middle = clean(employee.middleName || employee.middle_name);\n const last = clean(employee.lastName || employee.last_name);\n const display = clean(employee.displayName || employee.fullName || employee.full_name);\n\n return Array.from(new Set([\n display,\n [first, middle, last].filter(Boolean).join(' '),\n [first, last].filter(Boolean).join(' '),\n ].map(clean).filter(Boolean)));\n}\n\nconst employees = Array.isArray(raw.employees)\n ? raw.employees\n : Array.isArray(raw.data?.employees)\n ? raw.data.employees\n : [];\n\nif (!employees.length) {\n throw new Error('BambooHR no devolvió empleados para validar la corrección.');\n}\n\nconst candidates = employees.filter(countryMatches);\nif (!candidates.length) {\n throw new Error(`No se encontraron empleados de ${request.countryName} en BambooHR.`);\n}\n\nconst requestedNumber = normalizeIdentifier(request.bambooEmployeeNumber);\nlet matches = [];\nlet matchedBy = '';\n\nif (requestedNumber) {\n matches = candidates.filter((employee) =>\n normalizeIdentifier(employee.employeeNumber || employee.employee_number) === requestedNumber\n );\n matchedBy = 'employee_number';\n}\n\nif (!matches.length) {\n const targetName = normalizeName(request.bambooName);\n matches = candidates.filter((employee) =>\n employeeAliases(employee).some((alias) => normalizeName(alias) === targetName)\n );\n matchedBy = 'exact_bamboo_name';\n}\n\nif (matches.length !== 1) {\n if (matches.length > 1) {\n throw new Error('La identificación en BambooHR es ambigua. Indica el Employee Number para seleccionar una sola persona.');\n }\n\n throw new Error(\n 'No se encontró exactamente ese empleado en BambooHR para el país seleccionado. Revisa el nombre o indica el Employee Number.'\n );\n}\n\nconst employee = matches[0];\nconst aliases = employeeAliases(employee);\nconst actualName = clean(employee.displayName) || aliases[0] || request.bambooName;\nconst actualEmployeeNumber = clean(employee.employeeNumber || employee.employee_number);\nconst bambooId = clean(employee.employeeId || employee.id);\nconst now = new Date().toISOString();\n\nconst recipients = request.country === 'TT'\n ? ['lnicomejack@gomezleemarketing.com']\n : [\n 'pgamboa@gomezleemarketing.com',\n 'smeyer@gomezleemarketing.com',\n 'mjmorales@gomezleemarketing.com',\n ];\n\nconst aliasPayload = request.sourceNames.map((sourceName) => ({\n pais: request.country,\n nombre_origen: sourceName,\n nombre_origen_normalizado: normalizeName(sourceName),\n cuenta_bancaria: String(request.bankAccount || '').replace(/[^0-9A-Za-z]+/g, ''),\n bamboo_employee_number: actualEmployeeNumber || null,\n bamboo_employee_id: bambooId || null,\n bamboo_nombre: actualName,\n motivo: request.reason,\n comentario: request.comment || null,\n activo: true,\n validado_por_email: request.requestedByEmail,\n validado_por_nombre: request.requestedByName,\n last_reported_at: now,\n updated_at: now,\n}));\n\nreturn [{\n json: {\n request,\n matchedBy,\n employee: {\n bambooId,\n employeeNumber: actualEmployeeNumber,\n name: actualName,\n status: clean(employee.status),\n location: clean(employee.location),\n },\n recipients,\n aliasPayload,\n },\n}];"
|
||||
"jsCode": "const request = $('Validar usuario').first().json || {};\nconst raw = $input.first().json || {};\n\nfunction clean(value) {\n return String(value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction normalizeName(value) {\n return clean(value)\n .toLowerCase()\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-z0-9 ]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction normalizeIdentifier(value) {\n return clean(value).toUpperCase().replace(/[^A-Z0-9]/g, '');\n}\n\nfunction countryMatches(employee) {\n const location = normalizeName(\n employee.location ||\n employee.jobInformationLocation ||\n employee.jobLocation ||\n employee.country ||\n ''\n );\n\n if (request.country === 'GT') {\n return location.includes('guatemala');\n }\n\n return location.includes('trinidad') || location.includes('tobago');\n}\n\nfunction employeeAliases(employee) {\n const first = clean(employee.firstName || employee.first_name);\n const middle = clean(employee.middleName || employee.middle_name);\n const last = clean(employee.lastName || employee.last_name);\n const display = clean(employee.displayName || employee.fullName || employee.full_name);\n\n return Array.from(new Set([\n display,\n [first, middle, last].filter(Boolean).join(' '),\n [first, last].filter(Boolean).join(' '),\n ].map(clean).filter(Boolean)));\n}\n\nconst employees = Array.isArray(raw.employees)\n ? raw.employees\n : Array.isArray(raw.data?.employees)\n ? raw.data.employees\n : [];\n\nif (!employees.length) {\n throw new Error('BambooHR no devolvió empleados para validar la corrección.');\n}\n\nconst candidates = employees.filter(countryMatches);\nif (!candidates.length) {\n throw new Error(`No se encontraron empleados de ${request.countryName} en BambooHR.`);\n}\n\nconst requestedNumber = normalizeIdentifier(request.bambooEmployeeNumber);\nlet matches = [];\nlet matchedBy = '';\n\nif (requestedNumber) {\n matches = candidates.filter((employee) =>\n normalizeIdentifier(employee.employeeNumber || employee.employee_number) === requestedNumber\n );\n matchedBy = 'employee_number';\n}\n\nif (!matches.length) {\n const targetName = normalizeName(request.bambooName);\n matches = candidates.filter((employee) =>\n employeeAliases(employee).some((alias) => normalizeName(alias) === targetName)\n );\n matchedBy = 'exact_bamboo_name';\n}\n\nif (matches.length !== 1) {\n if (matches.length > 1) {\n throw new Error('La identificación en BambooHR es ambigua. Indica el Employee Number para seleccionar una sola persona.');\n }\n\n throw new Error(\n 'No se encontró exactamente ese empleado en BambooHR para el país seleccionado. Revisa el nombre o indica el Employee Number.'\n );\n}\n\nconst employee = matches[0];\nconst aliases = employeeAliases(employee);\nconst actualName = clean(employee.displayName) || aliases[0] || request.bambooName;\nconst actualEmployeeNumber = clean(employee.employeeNumber || employee.employee_number);\nconst bambooId = clean(employee.employeeId || employee.id);\nconst now = new Date().toISOString();\n\nconst recipients = request.country === 'TT'\n ? ['lnicomejack@gomezleemarketing.com']\n : ['haguirre@gomezleemarketing.com'];\n\nconst aliasPayload = request.sourceNames.map((sourceName) => ({\n pais: request.country,\n nombre_origen: sourceName,\n nombre_origen_normalizado: normalizeName(sourceName),\n cuenta_bancaria: String(request.bankAccount || '').replace(/[^0-9A-Za-z]+/g, ''),\n bamboo_employee_number: actualEmployeeNumber || null,\n bamboo_employee_id: bambooId || null,\n bamboo_nombre: actualName,\n motivo: request.reason,\n comentario: request.comment || null,\n activo: true,\n validado_por_email: request.requestedByEmail,\n validado_por_nombre: request.requestedByName,\n last_reported_at: now,\n updated_at: now,\n}));\n\nreturn [{\n json: {\n request,\n matchedBy,\n employee: {\n bambooId,\n employeeNumber: actualEmployeeNumber,\n name: actualName,\n status: clean(employee.status),\n location: clean(employee.location),\n },\n recipients,\n aliasPayload,\n },\n}];"
|
||||
},
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1200,
|
||||
0
|
||||
1456,
|
||||
528
|
||||
],
|
||||
"id": "504eed05-c6be-442e-9707-8cd4aca1d19c",
|
||||
"id": "bb82de3a-cbbf-479c-a2da-96b677cb6eda",
|
||||
"name": "Resolver empleado BambooHR"
|
||||
},
|
||||
{
|
||||
@@ -728,10 +728,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
1440,
|
||||
0
|
||||
1696,
|
||||
528
|
||||
],
|
||||
"id": "6fc69ac2-6999-4810-9e8d-675c4c4d40ac",
|
||||
"id": "062d8846-d24a-4887-9ef3-7de4a5d204d4",
|
||||
"name": "Guardar alias Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -744,10 +744,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
1680,
|
||||
0
|
||||
1936,
|
||||
528
|
||||
],
|
||||
"id": "9d565bf5-a6df-4ac9-bad1-abe48a277c37",
|
||||
"id": "3c1d6a0d-c096-4b31-9ba9-4ce2ec357f8e",
|
||||
"name": "Preparar auditoría"
|
||||
},
|
||||
{
|
||||
@@ -785,10 +785,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
1920,
|
||||
0
|
||||
2176,
|
||||
528
|
||||
],
|
||||
"id": "45f87d7b-a746-4eb2-a54e-d2de7645f854",
|
||||
"id": "9cd76301-127f-449a-a8c5-1bcdfe79de9a",
|
||||
"name": "Guardar solicitud Supabase",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -801,10 +801,10 @@
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
2160,
|
||||
0
|
||||
2416,
|
||||
528
|
||||
],
|
||||
"id": "68be3c1d-42eb-4bc5-aa35-36333261f2a6",
|
||||
"id": "6f05bfa0-78b5-4447-a440-19f90c6f7bba",
|
||||
"name": "Preparar correo RRHH"
|
||||
},
|
||||
{
|
||||
@@ -819,10 +819,10 @@
|
||||
"type": "n8n-nodes-base.gmail",
|
||||
"typeVersion": 2.2,
|
||||
"position": [
|
||||
2400,
|
||||
0
|
||||
2656,
|
||||
528
|
||||
],
|
||||
"id": "28f7c657-0c5b-47c6-898b-f68f1cf21378",
|
||||
"id": "9822f786-4c81-4a07-94ed-081e8485cbba",
|
||||
"name": "Enviar correo RRHH",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 3,
|
||||
@@ -870,10 +870,10 @@
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4.4,
|
||||
"position": [
|
||||
2640,
|
||||
0
|
||||
2896,
|
||||
528
|
||||
],
|
||||
"id": "87b7910e-0465-40b1-89d4-6b160726b7f7",
|
||||
"id": "3e801286-89a6-4e29-a443-4c1f5e5afe14",
|
||||
"name": "Marcar correo enviado",
|
||||
"retryOnFail": true,
|
||||
"maxTries": 2,
|
||||
@@ -898,10 +898,10 @@
|
||||
"type": "n8n-nodes-base.respondToWebhook",
|
||||
"typeVersion": 1.5,
|
||||
"position": [
|
||||
2880,
|
||||
0
|
||||
3136,
|
||||
528
|
||||
],
|
||||
"id": "1db48431-4661-49de-a495-66c740b2aac1",
|
||||
"id": "4359eea0-0f16-4241-840f-565d56700bb5",
|
||||
"name": "Respond to Webhook"
|
||||
}
|
||||
],
|
||||
@@ -1040,15 +1040,15 @@
|
||||
}
|
||||
},
|
||||
"authors": "Isaac Aracena",
|
||||
"name": "Version 7e4daa40",
|
||||
"name": "Version a190ab40",
|
||||
"description": "",
|
||||
"autosaved": true,
|
||||
"workflowPublishHistory": [
|
||||
{
|
||||
"createdAt": "2026-08-11T18:47:55.639Z",
|
||||
"id": 4454,
|
||||
"createdAt": "2026-08-19T14:20:03.066Z",
|
||||
"id": 4943,
|
||||
"workflowId": "0yaiagL1tWdhRUXy",
|
||||
"versionId": "7e4daa40-244f-43ed-9d74-14a9cb589ddf",
|
||||
"versionId": "a190ab40-7527-4805-a7ac-cc26ed1e558b",
|
||||
"event": "activated",
|
||||
"userId": "0a88c0b1-928e-4412-896e-c5d1c99b2029"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user