Files
encuesta-terminacion-volunt…/documentacion_workflow_n8n.md
T
2026-06-16 15:20:01 +00:00

238 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Documentación Técnica del Workflow: Encuesta de Terminación Voluntaria (n8n)
Este documento detalla el diseño, la lógica de negocio y la configuración paso a paso de los nodos del flujo automatizado desarrollado en n8n para la gestión inteligente de encuestas de salida laboral de **GomezLee Marketing**.
---
## 1. Descripción del Proyecto y Alcance
El propósito fundamental de este flujo es optimizar la recolección y análisis de datos procedentes de las encuestas de salida de los empleados con terminación voluntaria.
### El Problema
Históricamente, muchos empleados seleccionan o escriben motivos genéricos como **"Motivos Personales"** o proveen respuestas sin sentido o ambiguas en los formularios de salida. Esto impide que el departamento de Recursos Humanos (RRHH) obtenga información de valor (*insights*) para implementar planes de retención y mejoras internas.
### La Solución Automatizada
El workflow soluciona este problema mediante un ciclo inteligente dividido en tres fases principales (visibles en la estructura del flujo de `image_ec77fb.jpg`):
1. **Fase de Envío Automatizado:** Identifica bajas voluntarias del sistema central (BambooHR) y envía la encuesta formal de manera automatizada.
2. **Fase de Análisis y Homologación Inicial (IA):** Recibe la respuesta del formulario, utiliza Inteligencia Artificial (Google Gemini) para clasificar el motivo real, detectar subcategorías, evaluar el sentimiento e insertarlo en una base de datos (Google Sheets).
3. **Fase de Excepción y Recolección de Datos (RRHH + Email Loop):** Si el motivo detectado o declarado cae bajo "Motivos Personales" o es "No Declarado", se activa un condicional que notifica inmediatamente al analista de RRHH del país correspondiente. RRHH llama al exempleado, obtiene el motivo detallado y responde un correo electrónico formateado. El sistema procesa esta respuesta vía email, re-homologa la información con IA y actualiza el registro inicial en el Google Sheets de manera transparente.
---
## 2. Diagrama Estructural del Workflow
De acuerdo al archivo técnico y a la imagen de referencia `image_ec77fb.jpg`, el workflow se compone de 4 sub-procesos o bloques lógicos claramente demarcados:
* **Sub-proceso 1 (Arriba):** Trigger Webhook de terminación y validación en BambooHR de que sea baja voluntaria del mes en curso para el envío de la encuesta de salida.
* **Sub-proceso 2 (Centro):** Webhook de recepción de respuestas del formulario, procesamiento por IA (Gemini), guardado en Google Sheets, filtro condicional de excepción e inicio del bucle de correos hacia RRHH.
* **Sub-proceso 3 (Abajo - Recepción):** Listener / Trigger de Gmail que captura los correos de RRHH cuando la información es refinada, re-clasifica el motivo real con IA y actualiza la fila correspondiente en Google Sheets.
* **Sub-proceso 4 (Fondo):** Flujo técnico de respaldo/automatización interna para guardar copias del JSON del workflow en un repositorio Git centralizado.
---
## 3. Configuración Nodo por Nodo y Valores Recomendados
A continuación se detallan los parámetros y valores específicos que deben colocarse en cada nodo para garantizar el funcionamiento preciso del sistema:
### Bloque A: Envío de la Encuesta (Bajas Voluntarias)
#### 1. Webhook (Entrada de Terminación)
* **Tipo de Nodo:** `n8n-nodes-base.webhook`
* **HTTP Method:** `POST`
* **Path:** `terminacion`
* **Función:** Recibe las notificaciones de eventos de personal/bajas desde el core de RRHH.
#### 2. If (Validación de Tipo)
* **Tipo de Nodo:** `n8n-nodes-base.if`
* **Condición (String):**
* **Value 1:** `{{ $json.body.employees[0].fields['Tipo de despido'] }}`
* **Operator:** `Equal`
* **Value 2:** `Resignation (Voluntary)`
#### 3. Fecha de terminacion
* **Tipo de Nodo:** `n8n-nodes-base.httpRequest`
* **Method:** `GET`
* **URL:** `https://api.bamboohr.com/api/gateway.php/glm/v1/employees/{{ $json.body.employees[0].id }}?fields=terminationDate`
* **Authentication:** `HTTP Basic Auth` -> Usar credenciales `GLM Credential`.
* **Headers:** `accept: application/json`
#### 4. Code in JavaScript3 (Filtro Temporal)
* **Tipo de Nodo:** `n8n-nodes-base.code`
* **Código JS:**
```javascript
const terminationDate = $json.terminationDate;
if (!terminationDate) return [{ json: { pass: false } }];
const termDate = new Date(terminationDate);
const now = new Date();
const sameMonth = termDate.getMonth() === now.getMonth();
const sameYear = termDate.getFullYear() === now.getFullYear();
return [{ json: { pass: sameMonth && sameYear } }];
```
#### 5. Terminacion fue este mes?
* **Tipo de Nodo:** `n8n-nodes-base.if`
* **Condición (Boolean):**
* **Value 1:** `{{ $json.pass }}`
* **Operator:** `is True`
#### 6. Send a message (Gmail)
* **Tipo de Nodo:** `n8n-nodes-base.gmail`
* **Resource:** `Message`
* **Operation:** `Send`
* **Send To:** `{{ $('Webhook').item.json.body.employees[0].fields['Correo electrónico personal'] }}`
* **Subject:** `GomezLee Marketing: Encuesta de salida Queremos escuchar tu opinión`
* **Body Type:** `HTML`
* **Message:** *(Insertar el código HTML provisto en la definición del flujo que renderiza la plantilla corporativa con el botón directo a la encuesta de Google Forms).*
---
### Bloque B: Procesamiento de Respuestas de Encuesta e IA
#### 7. Webhook1 (Recepción del Formulario)
* **Tipo de Nodo:** `n8n-nodes-base.webhook`
* **HTTP Method:** `POST`
* **Path:** `encuesta`
#### 8. Code in JavaScript (Timestamping)
* **Tipo de Nodo:** `n8n-nodes-base.code`
* **Código JS:** Genera una estampa de tiempo formateada (`MM/DD/YYYY HH:MM:SS`) para consistencia en la hoja de cálculo.
#### 9. AI Agent + Google Gemini Chat Model (Clasificador Inicial)
* **Tipo de Nodo:** `@n8n/n8n-nodes-langchain.agent` conectado a `lmChatGoogleGemini`.
* **Model Name:** `models/gemini-3.1-pro-preview`
* **Prompt Text:** `={{ $('Webhook1').item.json.body['¿Por qué elegiste dejar la empresa?'] }}`
* **System Message (Clave):** Debe instruirse rigurosamente al modelo a actuar como un analista experto de RRHH para trade marketing y mapear el texto a etiquetas estructuradas de salida. Los labels válidos requeridos son:
* `"Motivos Personales"`
* `"Remuneración"`
* `"Liderazgo / Jefe Directo"`
* `"Otro Trabajo / Traslado de Agencia"`
* `"Ambiente Laboral / Compañeros"`
* `"Work Life Balance / Horarios"`
* `"Marca / Cliente / Condiciones del Punto"`
* `"Onboarding / Procesos / Organización"`
* `"Way of Work / Soporte Operativo"`
* `"Reclutamiento / Expectativa vs Realidad"`
* `"No quiso responder"`, `"Motivo No Declarado"`, o `"Otros"`.
* **Estructura del Output Requerido (JSON puro sin backticks):**
```json
{
"homologacion": "string",
"homologado_2": "string | null",
"sentimiento": "Positivo | Neutro | Negativo",
"insight_rrhh": "frase breve con hallazgo clave"
}
```
#### 10. Code in JavaScript1 (Limpieza de Formato IA)
* **Tipo de Nodo:** `n8n-nodes-base.code`
* **Objetivo:** Elimina bloques de markdown (como \`\`\`json) en caso de que el LLM rompa las restricciones de formato, aislando la cadena JSON cruda.
#### 11. Edit Fields & Eliminar espacios vacios
* **Tipo de Nodos:** `n8n-nodes-base.set` y `n8n-nodes-base.code`.
* **Función:** Mapean y remueven espacios en blanco colindantes en los nombres y cadenas para evitar inconsistencias de llaves primarias.
#### 12. Añadir a Responses (Google Sheets)
* **Tipo de Nodo:** `n8n-nodes-base.googleSheets`
* **Operation:** `Append`
* **Document ID:** `1_vEMMGBclOZxaTeuHLXO_ucN0GmJ03Gm7jzOlzkVMFA`
* **Sheet Name:** `Respuestas`
* **Mapeo de Columnas (Expresiones):**
* `Homologacion_IA`: `{{ $('Edit Fields').item.json.cleaned.homologacion }}`
* `Subcategoria_IA`: `{{ $('Edit Fields').item.json.cleaned.homologado_2 }}`
* `Sentimiento_IA`: `{{ $('Edit Fields').item.json.cleaned.sentimiento }}`
* `Insight_RRHH`: `{{ $('Edit Fields').item.json.cleaned.insight_rrhh }}`
* `Timestamp`: `{{ $('Webhook1').item.json.body.timestamp }}`
* `Email Address`: `{{ $('Webhook1').item.json.body.email }}`
* `Nombre Completo`: `{{ $json.name }}`
* `¿Por qué elegiste dejar la empresa?`: `{{ $('Webhook1').item.json.body['¿Por qué elegiste dejar la empresa?'] }}`
#### 13. Es motivo personal? (El Enrutador de Excepciones)
* **Tipo de Nodo:** `n8n-nodes-base.if`
* **Lógica de Evaluación Expresa (JavaScript Emulado):**
```javascript
{{
(() => {
const allowed = ["motivos personales", "motivo no declarado"];
const homol = ($json.Homologacion_IA ?? "").toLowerCase().trim();
const sub = ($json.Subcategoria_IA ?? "").toLowerCase().trim();
const homolOk = homol === "" || allowed.includes(homol);
const subOk = sub === "" || allowed.includes(sub);
const anyFilled = homol !== "" || sub !== "";
return anyFilled && homolOk && subOk;
})()
}}
```
* **Operator:** `is True`
* **Comportamiento:** Si da verdadero (True), significa que la respuesta de la persona no es accionable y requiere intervención de RRHH.
#### 14. Paises (Ruteo Geográfico de RRHH)
* **Tipo de Nodo:** `n8n-nodes-base.code`
* **Propósito:** Mapea el país del empleado al correo del analista encargado en esa región.
* **Diccionario de Mapeo:**
* Dominicana: `nlaureano@gomezleemarketing.com`
* Guatemala: `rgalvez@gomezleemarketing.com`
* El Salvador: `cmalta@gomezleemarketing.com`
* Honduras: `mchang@gomezleemarketing.com`
* Nicaragua: `yestrada@gomezleemarketing.com`
* Costa Rica: `lchaves@gomezleemarketing.com`
* México: `ccastro@gomezleemarketing.com`
* Colombia: `rrhhcolombia@gomezleemarketing.com`
* Panamá: `dpenalba@gomezleemarketing.com`
#### 15. Enviar revision (Notificación a Analista)
* **Tipo de Nodo:** `n8n-nodes-base.gmail`
* **Send To:** `{{ $json.hhrr_email }}`
* **Subject:** `Seguimiento requerido Encuesta de Salida`
* **Contenido:** Envía un correo con la ficha del exempleado pidiendo realizar la llamada y especificando que deben responder al sistema manteniendo el asunto: **"Motivo de Salida Actualizado"** e incluyendo en el cuerpo obligatoriamente las líneas:
```text
Nombre completo: [Nombre Exacto]
Motivo: [Nuevo Motivo Detallado]
```
---
### Bloque C: Procesamiento del Correo de Actualización (RRHH Loop)
#### 16. Gmail Trigger (Listener de Respuestas de RRHH)
* **Tipo de Nodo:** `n8n-nodes-base.gmailTrigger`
* **Filters:**
* **Search Query (q):** `Motivo de Salida Actualizado`
* **Read Status:** `Read`
#### 17. Limpiar texto
* **Tipo de Nodo:** `n8n-nodes-base.code`
* **Código JS:** Remueve firmas automáticas y descargos legales buscando el marcador corporativo `'gomezlee marketing'` para evitar ruidos en el análisis sintáctico de la IA.
#### 18. AI Agent1 + Google Gemini Chat Model1 (Re-homologación)
* **Tipo de Nodo:** `@n8n/n8n-nodes-langchain.agent`
* **Model Name:** `models/gemini-3.1-pro-preview`
* **Prompt Text:** `={{ $json.body }}`
* **Instrucciones del Sistema:** Extrae el `nombre_completo` y el nuevo `motivo`. Re-clasifica según las categorías estándar de la organización y genera un nuevo output estructurado:
```json
{
"nombre_completo": "string",
"homologacion": "string",
"homologado_2": "string | null",
"sentimiento": "Positivo | Neutro | Negativo",
"insight_rrhh": "string",
"motivo": "string"
}
```
#### 19. Añadir a Responses1 (Google Sheets Update)
* **Tipo de Nodo:** `n8n-nodes-base.googleSheets`
* **Operation:** `Update`
* **Document ID:** `1_vEMMGBclOZxaTeuHLXO_ucN0GmJ03Gm7jzOlzkVMFA`
* **Sheet Name:** `Respuestas`
* **Columnas a Actualizar:**
* `Homologacion_IA`: `{{ $('Edit Fields1').item.json.output.homologacion }}`
* `Subcategoria_IA`: `{{ $('Edit Fields1').item.json.output.homologado_2 }}`
* `Sentimiento_IA`: `{{ $('Edit Fields1').item.json.output.sentimiento }}`
* `Insight_RRHH`: `{{ $('Edit Fields1').item.json.output.insight_rrhh }}`
* `¿Por qué elegiste dejar la empresa?`: `{{ $('Edit Fields1').item.json.output.motivo }}`
* **Key/Matching Columns:** `Nombre Completo` *(Garantiza la sobreescritura exacta del registro que antes estaba bloqueado en motivos personales).*
---
## 4. Instrucciones de Despliegue y Pruebas
1. **Credenciales:** Asegurarse de enlazar la cuenta OAuth2 de Google Sheets (`Eidan - Google Sheets account`), Gmail (`Eidan - Gmail account`), Google Gemini (`Eidan - Google Gemini(PaLM) Api account`) y la API de BambooHR.
2. **Activación de Triggers:** Pasar el estado del workflow en n8n de `Inactive` a `Active`.
3. **Monitoreo:** En caso de errores en la estructura del JSON devuelto por Gemini, el nodo intermedio `Code in JavaScript1` y `Limpiar texto` actuarán como capas de sanitización automáticas.