Files
calendario-glm-way/README.md
T
2026-08-27 19:56:51 +00:00

17 KiB
Raw Blame History

#TheGLMWay — Workflow de Automatización Onboarding (n8n)

Sistema automatizado que detecta nuevos ingresos en BambooHR, los inscribe en la sesión de GLM Way correspondiente a su idioma, gestiona toda la comunicación pre-sesión y recolecta la evaluación post-sesión.

ID Workflow: F1iPg8hktNAebZua · Nombre: GLMWay · Timezone: America/Santo_Domingo · Estado: Activo


1. Propósito

Centralizar y automatizar el ciclo de vida completo de la capacitación #TheGLMWay para nuevos colaboradores:

  1. Detectar el ingreso (hireDate) en BambooHR el día 1.
  2. Asignar al colaborador a la sesión más cercana según su idioma (país → ES/EN).
  3. Notificarle por email con fecha, hora localizada y enlace de Meet.
  4. Avisar al coordinador RRHH del país y al facilitador 48h / 24h antes.
  5. Enviar recordatorio al colaborador 24h antes.
  6. Verificar asistencia real vía Google Meet API y enviar evaluación (Google Forms) post-sesión.
  7. Medir métricas de evaluaciones enviadas/respondidas.

Todo persiste en Supabase (inscritos_glmway, sesiones_glmway, coordinadores_rrhh_glmway) y se sincroniza con Google Calendar / Sheets / Chat.


2. Arquitectura General

BambooHR (Webhook + Polling) ─┬─► Supabase (inscritos_glmway)
                              │
Google Calendar (ethen@) ─────┼─► Supabase (sesiones_glmway)
Google Sheets (Calendario) ───┼─► Supabase (coordinadores_rrhh_glmway)
                              │
                              ├─► Gmail (notificación + recordatorio + evaluación)
                              ├─► Google Chat (facilitador + coordinadores RRHH)
                              └─► WhatsApp Evolution API (alerta sin coordinador)
Meet API ─────────────────────► Asistencia ─► Evaluación
Gitea (git.digitalcompass.agency) ─► Backup JSON del workflow

Credenciales utilizadas:

Servicio Credencial n8n Uso
BambooHR Eidan - BambooHR account + GLM Credential (Basic Auth) Get an employee, HTTP /employees/{id}
Supabase Sofia test - Supabase account Tablas inscritos_glmway, sesiones_glmway, coordinadores_rrhh_glmway, RPCs
Gmail Eidan - Gmail account (OAuth2) 10 nodos Send a message
Google Calendar Eidan - Google Calendar account Lectura ethen@gomezleemarketing.com query #TheGLMWay
Google Sheets Eidan - Google Sheets account Sheet 1Xs-MkeXiZvWeJuwm-IblcI-ilr7lyhMtED0R7wczmRg
Google Chat Eidan - Chat account (OAuth) Spaces AAQAgX1mjaY (GLMWay), AAQAQj1t9AA (RRHH)
Google Contacts Eidan - Google Contacts account Resolución contactId para menciones <users/...> en Chat
Google Meet Eidan - Google account (OAuth2) meet.googleapis.com/v2/conferenceRecords
Gitea Eidan - gitea (headerAuth) Backup mgomez/calendario-glm-way:glmway-workflow.json
n8n API Eidan - n8n account Get a workflow para backup
WhatsApp Evolution API wsp.gomezleemarketing.com botsoporte Alerta a 18494105855@s.whatsapp.net

3. Modelo de Datos (Supabase)

inscritos_glmway

Campo Tipo Descripción
empleado_id text PK ID BambooHR
nombre text displayName
email text workEmail
departamento text department
division text division
puesto text jobTitle
pais text location (BambooHR)
fecha_ingreso date hireDate YYYY-MM-DD
fecha_sesion_inscrito text "14 January" (sesión asignada)
sesion_id text FK sesiones_glmway.id
estado text inactivonotificadorecordadoevaluacion_enviada
coordinador_rrhh text nombre coordinador del país
instructor text actualizado post-sesión
asistio_evento_glmway bool asistencia detectada Meet
fecha_sesion_inscrito text reutilizado para cálculo 24h

Estados: inactivo (registrado sin email), notificado (email inicial enviado), recordado (recordatorio 24h), evaluacion_enviada (evaluación enviada).

sesiones_glmway

Campo Descripción
id / meet_id ID evento Calendar / Meet
titulo "Entrenamiento #TheGLMWay" o "#TheGLMWay Training"
fecha_sesion "14 January"
hora_inicio / hora_fin HH:mm (hora Santo Domingo)
instructor Nombre del facilitador
correo_instructor Email
enlace_reunion / url Meet link
idioma ES / EN
participantes JSONB {"RD": [{nombre, correo, departamento, division}], "Mexico": [...]}

RPCs: insertar_participantes_sesion_glmway(p_sesion_id, p_pais, p_empleados), sync_sesiones_glmway, insertar_coordinadores_rrhh_glmway, incrementar_evaluaciones_enviadas_glmway, incrementar_evaluaciones_resueltas_glmway.

coordinadores_rrhh_glmway

Campo Descripción
pais País asignado
nombre Nombre completo
correo Email
estado no_notificado (filtro)

4. Lógica de Idioma por País

// ES = país NO está en lista Caribe anglófono
// EN = país SÍ está en lista
["Jamaica","Trinidad and Tobago","Barbados","Saint Thomas","St. Croix","Tobago","Guyana","Aruba"]

Todos los nodos Pais?, Pais?1, Pais?2, Pais?3, Pais?4 usan esta lista. Si falta coordinador para el país, se dispara alerta WhatsApp a Matos (18494105855).

Conversión de hora: todos los Cambiar zona horaria* (6 nodos) toman hora_inicio en America/Santo_Domingo como base y la convierten con Intl.DateTimeFormat al timezone del país del colaborador (mapa TIMEZONES con 25 países).


5. Flujos Detallados (10 sub-workflows en 1 workflow)

Flujo A — Notificación Inicial (Webhook BambooHR)

Trigger: Webhook POST /glmway (BambooHR webhook nuevos ingresos)

Webhook → Get an employee → Info extra (hireDate, supervisorEmail, jobTitle)
  → Calcular fecha hireDate (isValid = hireDate <= today)
  → Tiene correo y pais? ─┬─ NO → Insertar inscritos (inactivo)
                          └─ SI → Entra hoy? ─┬─ NO  → Insertar inscritos (inactivo)
                                              └─ SI  → Obtener coordinador3
                                                       → Hay coordinador? ─ NO → Alerta WhatsApp + Pais?
                                                                               SI → Pais? → [ES/EN]
                                                                                → Crear variable idioma
                                                                                → Obtener sesiones (filtro idioma)
                                                                                → Calcular sesion mas cercana
                                                                                → Guardar datos empleado+sesion (estado=notificado)
                                                                                → Convertir fecha a es/en
                                                                                → Cambiar zona horaria
                                                                                → Send Gmail (ES/EN)
                                                                                → Registrar empleado a sesión (RPC)

Templates Gmail: Entrenamiento #TheGLMWay / #TheGLMWay Training con fechaFormateada, hora_convertida, enlace_reunion.

Flujo B — Reintento Inactivos (Polling Horario)

Trigger: Schedule Trigger1 — cada hora

Obtener inactivos (estado=inactivo) → Loop Over Items (SplitInBatches)
  → Get an employee1 → Info extra 1 → Calcular fecha hireDate1 → Tiene correo y pais?1
  → Entra hoy?1 ─ SI → Obtener coordinador4 → Hay coordinador?1 → Pais?1 → (mismo camino ES/EN)
               → Actualizar datos del empleado y sesion asignada → ... → Send Gmail 1
  → NO → Wait2 2s → Loop

Flujo C — Recordatorio 24h al Colaborador

Trigger: Schedule Trigger2 — martes y miércoles 17:00

Obtener notificados (estado=notificado) → Loop Over Items1
  → Calcular falta 24h o es el mismo dia (parsea "14 December", diferenciaDias 0-1)
  → Falta 24h para el evento? ─ SI → Obtener sesion → Pais?2 → Convertir fecha 2
                              → Cambiar zona horaria 4/5 → Send Gmail recordatorio
                              → Actualizar estado a recordado → Wait1 2s → Loop
                            ─ NO → Wait1 → Loop

Asunto recordatorio ES: Entrenamiento #TheGLMWayTexto: “Te recordamos que la sesión será el {{fecha}} a las {{hora}}...”

Flujo D — Notificación a Facilitador (48h / día del evento)

Trigger: Schedule Trigger — miércoles 16:00

Obtener sesion1 (todas) → Calcular sesion mas cercana4 (match hoy)
  → Obtener miembros (Chat Space AAQAgX1mjaY) → Limpiar id → Get a contact → Unir datos2
  → Hay inscritos? ─ SI → Es espanol o ingles1 (switch por idioma sesión)
                      → Formatear datos ingles/espanol (card con totalParticipantes, enlace)
                      → Enviar notificación a glmway notificaciones
                    ─ NO → Es espanol o ingles (switch)
                      → Formatear datos ingles1/espanol1 (card “No hay participantes”)
                      → Enviar notificación

Si hay inscritos: 🔔 *Recordatorio de #TheGLMWay para hoy* \n Instructor: <users/...> con totalParticipantes y Entrar a reunión. Si no: 🔔 *Aviso de sesión sin participantes*.

Flujo E — Notificación a Coordinador RRHH (48h + 24h)

Trigger: Schedule Trigger3 — martes 16:00 + miércoles 16:00

Obtener sesiones (all) → Calcular falta 48h o 24h1 (sesión más cercana futura)
  → Hay inscritos en la sesion? ─ SI → Obtener coordinadores1 (estado=no_notificado filtro)
                                 → Matchear coordinador y pais inscrito (normaliza acentos)
                                 → Obtener miembros RRHH (AAQAQj1t9AA) → Limpiar id1 → Get a contact1
                                 → Unir datos3 (match nombre coordinador ↔ Google Contact)
                                 → Pais?3 → Formatear datos ingles2/espanol2
                                 → Enviar notificación a rrhh notificaciones

Card RRHH: 🔔 *Aviso para Coordinadores RRHH* con Total inscritos: X + listado por país 📍 RD (2): • Nombre (Depto | División).

Flujo F — Post-Sesión: Asistencia + Evaluación

Trigger: Schedule Trigger7 — miércoles 19:50 (post-sesión)

Hora de la reunion (timestamp → startTime T22:50:24Z, endTime T24:00:00Z, fechaCorta "11 August")
  → Obtener conferenceRecord (Meet API v2) → Buscar sesion con hora UTC (filtra por fecha, distanciaMs mínima)
  → Obtener participantes (conferenceRecords/{name}/participants)
  → Detectar participantes en la sesion (extrae signedinUser.displayName)
  → Obtener sesion2 (por fecha_sesion) ─┬─→ Buscar participantes (match normalizado displayName ↔ nombre registrado)
  │                                     └─→ Actualizar instructor de inscritos
  → Split Out (participantes) → Actualizar asistencia (supabase asistio_evento_glmway bool, wfts por nombre)
  → Asistio? (solo si asistio=false se envía evaluación — filtra asistentes? verificar lógica)
  → Cortar nombre (primerNombre) → Pais?4 → Send Gmail evaluación (HTML con branding GLM + botón Google Forms)
  → Actualizar estado a evaluacion_enviada → Incrementar conteo evaluaciones enviadas (RPC)

Evaluación ES: Evaluación #TheGLMWayhttps://docs.google.com/forms/d/e/1FAIpQLSf8QUfmXulvw4e9BwZjTFG4mEUWybdFSAes_dK-OFnWN-L43Q/viewform con header #2d3748 + logo GLM. EN: #TheGLMWay Quiz...Sf61KpkDr....

Flujo G — Webhook Evaluación Respondida

Trigger: Webhook1 POST /evaluacion-glmway

Webhook1 → Incrementar conteo de evaluaciones respondidas (RPC incrementar_evaluaciones_resueltas_glmway)

Flujo H — Sincronización Anual Calendario → Sheets

Trigger: Schedule Trigger40 0 0 1 1 * (1 de enero)

Obtener entrenamientos ingles y espanol (Calendar año completo query #TheGLMWay)
  → Formatear fecha (DD Month) → Borrar fechas (Sheets rango A2:D80) → Wait4 → Insertar fechas (appendOrUpdate por Fecha)

Flujo I — Sincronización Diaria Coordinadores

Trigger: Schedule Trigger5 — diario 11:00

Obtener coordinadores (Sheets “Coordinadores RRHH”) → Aggregate (input) → Insertar/actualizar coordinadores a la bd (RPC)

Flujo J — Sincronización Diaria Sesiones

Trigger: Schedule Trigger6 — miércoles 15:00

Obtener fechas e instructores (Sheets Calendario)
+ Obtener entrenamientos ingles y espanol1 (Calendar)
  → Formatear fecha y detectar idioma (detecta "#TheGLMWay Training"→EN, "Entrenamiento #TheGLMWay"→ES, extrae hora_inicio/fin, url)
  → Unir datos (merge por Fecha) → Edit Fields (meet_id, titulo, fecha_sesion, hora_inicio/fin, instructor, correo_instructor, enlace_reunion, idioma)
  → Aggregate1 → Insertar fechas1 (RPC sync_sesiones_glmway)

Flujo K — Backup Automático del Workflow

Trigger: When clicking Execute workflow (manual)

Valores (mgomez / calendario-glm-way / glmway-workflow)
  → Obtener archivo (Gitea GET contents/*.json) ─┬─ éxito (onError continue) → Get a workflow1 → Code JS2 (base64 JSON + sha) → Actualizar archivo (PUT)
                                                 └─ error (no existe)       → Get a workflow2 → Code JS4 (base64)           → Subir archivo (POST)

6. Diagrama de Estados del Inscrito

[BambooHR hireDate futuro] ──► inactivo (insertado sin email/sin fecha)
        │
        ▼ (hireDate == today, con coordinador)
     notificado ──► (24h antes) ──► recordado
                                      │
                                      ▼ (post-sesión Meet)
                              evaluacion_enviada ──► (webhook) conteo respondida++

7. Notificaciones

Destinatario Canal Cuándo Formato
Nuevo ingreso Gmail Día 1 (Flujo A/B) Texto plano ES/EN con fecha, hora local, Meet link
Nuevo ingreso Gmail 24h antes (Flujo C) Recordatorio ES/EN
Facilitador Google Chat AAQAgX1mjaY Miércoles 16:00 (Flujo D) CardV2 con mención <users/...> + total participantes
Coordinador RRHH Google Chat AAQAQj1t9AA Mar/Mié 16:00 (Flujo E) CardV2 por país con listado detallado
Coordinador RRHH WhatsApp Sin coordinador (Flujo A/B) ⚠️ No hay coordinador RRHH en el país...
Inscrito Gmail Post-sesión 19:50 (Flujo F) HTML evaluación con botón a Google Forms

8. Instalación y Configuración

Requisitos

  • n8n ≥ 1.x con timezone America/Santo_Domingo
  • Credenciales: BambooHR API Key, Supabase service_role, Google OAuth (Calendar, Sheets, Gmail, Meet, Chat, Contacts), Gitea token, Evolution WhatsApp API key
  • Supabase: crear tablas + RPCs (insertar_participantes_sesion_glmway, sync_sesiones_glmway, etc.)
  • Google Sheet Calendario #TheGLMWay con hojas Calendario (col Fecha) y Coordinadores RRHH

Importar

  1. n8n → Import from FileGLMWay.json
  2. Reasignar credenciales (IDs en JSON son de instancia origen Eidan)
  3. Activar workflow
  4. Configurar webhook BambooHR → https://<n8n>/webhook/glmway (POST)
  5. Verificar Schedule Triggers — respetar horario Santo Domingo

Variables Clave a Revisar

  • WEBHOOK_URL base, wsp.gomezleemarketing.com apikey, git.digitalcompass.agency repo, ethen@gomezleemarketing.com calendar, Chat Space keys/tokens (rotar — están hardcodeados en nodos HTTP), Supabase URL dbit.digitalcompass.agency.

9. Operación y Monitoreo

  • Error Workflow: lX5ITf9s4TSQglsM (configurado en settings.errorWorkflow) — revisar ejecuciones fallidas.
  • Reintentos: Informacion extra del empleado con retry 2s, otros con retryOnFail: true.
  • Loops: Loop Over Items / Loop Over Items1 con Wait 2s para evitar rate-limit BambooHR/Gmail.
  • Logs: console.log en nodos Code (Sesiones procesadas, eventos ignorados).
  • PinData: Triggers con datos de prueba agosto 2026 — remover en prod.

10. Riesgos y Recomendaciones

Riesgo Mitigación sugerida
Tokens Chat hardcodeados (key=AIza...&token=...) en URLs Migrar a credencial googleChatOAuth2Api o variable de entorno, rotar tokens
service_role JWT expuesto en nodos HTTP Mover a credencial Header Auth, no en claro
TIMEZONES incompleto (faltan países GLM) Centralizar en tabla paises_timezones
Parseo fecha "14 January" frágil (locale/año) Usar date-fns con año explícito o ISO en sesiones_glmway
Duplicados por webhook + polling horario Añadir constraint único empleado_id + upsert
Wait fijo 2s puede exceder límites Gmail (100/día) Batch con SplitInBatches size controlado

11. Archivos Relacionados

  • GLMWay.json — definición completa del workflow (importable en n8n)
  • README_GLMWay.md — este documento

Documentado a partir de GLMWay.json vf657df3d-e5b6-445e-ad75-df66da81ebf3 — última edición inspeccionada 27/08/2026. GomezLee Marketing — Automatización #TheGLMWay.