Actualizar README.md
This commit is contained in:
@@ -1,408 +1,326 @@
|
||||
# Automatizacion GLM Way
|
||||
# #TheGLMWay — Workflow de Automatización Onboarding (n8n)
|
||||
|
||||
> **Sistema que detecta nuevos ingresos en BambooHR, los inscribe automaticamente en la sesion del GLM Way segun su idioma, los notifica el primer dia de trabajo, avisa al coordinador de RRHH 48 horas antes con la lista de inscritos, envia recordatorio 24 horas antes, y recolecta la evaluacion post-sesion.**
|
||||
> **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
|
||||
|
||||
---
|
||||
|
||||
## Informacion General
|
||||
## 1. Propósito
|
||||
|
||||
| Campo | Detalle |
|
||||
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 | `inactivo` → `notificado` → `recordado` → `evaluacion_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 |
|
||||
|---|---|
|
||||
| Proyecto | Automatizacion GLM Way |
|
||||
| Area | RRHH |
|
||||
| Estado | En Progreso |
|
||||
| Developer Principal | Eidan Then |
|
||||
| IT Manager | Luis Matos |
|
||||
| Fecha de Inicio | 2026-06-09 |
|
||||
| Fecha de Cierre Estimada | 2026-07-21 |
|
||||
| Ciclo Shape Up | Ciclo #N — Semana 1 de 6 |
|
||||
| Board de Ejecucion | [Link a Kan.bn — completar al crear el board] |
|
||||
| PRD del Proyecto | [Link al PRD en Gitea — completar al subir el PRD] |
|
||||
| `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`.
|
||||
|
||||
## Objetivo
|
||||
|
||||
### Problema que resuelve
|
||||
|
||||
El GLM Way es una induccion obligatoria para todos los nuevos ingresos de GLM a nivel regional. El proceso de inscripcion y notificacion es completamente manual: el coordinador de RRHH debe identificar a los nuevos ingresos en BambooHR, determinar a que sesion corresponde cada uno segun su idioma, enviarles el link del Google Meet, y luego recolectar las evaluaciones post-sesion. No existe ningun sistema de recordatorio ni seguimiento. Como resultado, nuevos ingresos no reciben la induccion porque el coordinador olvida notificarlos, y GLM no tiene visibilidad confiable de quien asistio y quien no.
|
||||
|
||||
### Solucion implementada
|
||||
|
||||
El sistema corre automaticamente en n8n sobre el servidor virtual GLM. Consulta BambooHR para detectar nuevos ingresos, determina su idioma por pais, identifica la proxima sesion en el calendario GLM Way (Google Sheets), y gestiona toda la cadena de comunicacion: notificacion el D1, aviso al coordinador 48hrs antes, recordatorio al empleado 24hrs antes, formulario de evaluacion post-sesion, y registro de asistencia en Supabase cruzando los attendees del Google Meet con los inscritos.
|
||||
|
||||
### Usuarios / Beneficiarios
|
||||
|
||||
- Nuevos ingresos de los 14 paises GLM — reciben notificaciones automaticas sin depender de un proceso manual.
|
||||
- Coordinadores de RRHH por pais — reciben un aviso proactivo 48hrs antes con la lista de quienes deben conectarse.
|
||||
- Luis Matos y Maximo Gomez — tienen visibilidad del programa en Supabase sin necesidad de seguimiento manual.
|
||||
|
||||
---
|
||||
|
||||
## Arquitectura
|
||||
|
||||
### Diagrama de flujo
|
||||
|
||||
```
|
||||
[BambooHR — nuevo ingreso detectado (hire_date = hoy)]
|
||||
|
|
||||
v
|
||||
[Identificar idioma por pais]
|
||||
|
|
||||
+---> [Espanol] ---> [Google Sheets: proxima sesion ES → fecha + link Meet]
|
||||
|
|
||||
+---> [Ingles] ---> [Google Sheets: proxima sesion EN → fecha + link Meet]
|
||||
|
|
||||
v
|
||||
[D1: Email al nuevo ingreso con fecha, hora y link de su sesion]
|
||||
|
|
||||
v
|
||||
[48hrs antes: Email al Coordinador de RRHH del pais con lista de inscritos]
|
||||
|
|
||||
v
|
||||
[24hrs antes: Email de recordatorio al nuevo ingreso]
|
||||
|
|
||||
v
|
||||
[Post-sesion (dentro de 1hr): Email con link del formulario de evaluacion ES / EN]
|
||||
|
|
||||
v
|
||||
[Google Calendar API: extraer attendees del Meet → cruzar vs inscritos → registrar asistencia en Supabase]
|
||||
```
|
||||
|
||||
### Stack tecnologico
|
||||
|
||||
| Componente | Tecnologia | Proposito |
|
||||
|---|---|---|
|
||||
| Automatizacion | n8n | Orquestacion de todos los flujos y schedulers |
|
||||
| Base de datos | Supabase / Postgres | Registro de inscritos, asistencia y evaluaciones |
|
||||
| RRHH | BambooHR API | Fuente de nuevos ingresos y datos del empleado |
|
||||
| Calendario | Google Sheets API | Lectura del calendario de sesiones y links de Meet |
|
||||
| Notificaciones | Gmail OAuth | Envio de emails a empleados y coordinadores |
|
||||
| Asistencia | Google Calendar API | Extraccion de attendees post-sesion |
|
||||
| Infraestructura | Servidor Virtual GLM | Hosting de n8n |
|
||||
|
||||
### Integraciones externas
|
||||
|
||||
| Sistema | Tipo de integracion | Datos que fluyen |
|
||||
|---|---|---|
|
||||
| BambooHR | API REST | Nuevos ingresos: nombre, email, pais, cargo, hire_date. Coordinadores: nombre, email, pais, posicion |
|
||||
| Google Sheets | API | Calendario GLM Way: fecha, facilitador, link Meet por idioma (ES / EN) |
|
||||
| Gmail | OAuth | Emails salientes: notificacion D1, aviso coordinador, recordatorio 24hrs, formulario evaluacion |
|
||||
| Google Calendar | API | Attendees del evento Meet post-sesion |
|
||||
| Supabase | Postgres directo | Tablas: inscritos_glmway, sesiones_glmway, asistencia_glmway |
|
||||
|
||||
---
|
||||
|
||||
## Reglas de negocio
|
||||
|
||||
### Logica de idioma por pais
|
||||
|
||||
| Idioma | Paises |
|
||||
### `coordinadores_rrhh_glmway`
|
||||
| Campo | Descripción |
|
||||
|---|---|
|
||||
| Ingles | Jamaica, Trinidad and Tobago, Guyana, St. Croix, Aruba, St. Thomas |
|
||||
| Espanol | Todos los demas paises GLM |
|
||||
|
||||
### Logica de inscripcion
|
||||
|
||||
- Rango de deteccion: empleados con hire_date entre la ultima sesion realizada y la proxima sesion programada.
|
||||
- Si hay multiples nuevos ingresos en la misma semana, todos van a la misma sesion proxima segun su idioma.
|
||||
- El sistema consulta el Google Sheet en tiempo real al momento del envio — nunca almacena el link con anticipacion.
|
||||
|
||||
### Logica del coordinador de RRHH
|
||||
|
||||
- El sistema busca en BambooHR empleados con Posicion = "Coordinador de RRHH" y Pais = pais del nuevo ingreso.
|
||||
- Si hay multiples coordinadores en un pais, el aviso se envia a todos.
|
||||
- Si no existe coordinador registrado para ese pais, se registra la excepcion en Supabase y se notifica a Luis Matos.
|
||||
|
||||
### Timing de notificaciones
|
||||
|
||||
| Notificacion | Destinatario | Cuando se envia |
|
||||
|---|---|---|
|
||||
| Notificacion inicial | Nuevo ingreso | hire_date = fecha actual (D1) |
|
||||
| Aviso con lista de inscritos | Coordinador de RRHH del pais | 48 horas antes de la sesion |
|
||||
| Recordatorio | Nuevo ingreso | 24 horas antes de la sesion |
|
||||
| Formulario de evaluacion | Nuevo ingreso | Dentro de la hora siguiente al fin de la sesion |
|
||||
| `pais` | País asignado |
|
||||
| `nombre` | Nombre completo |
|
||||
| `correo` | Email |
|
||||
| `estado` | `no_notificado` (filtro) |
|
||||
|
||||
---
|
||||
|
||||
## Configuracion y Setup
|
||||
## 4. Lógica de Idioma por País
|
||||
|
||||
### Prerequisitos
|
||||
|
||||
- [ ] Acceso a BambooHR API — API Key generada en BambooHR → Account → API Keys
|
||||
- [ ] Google Cloud project con Google Sheets API y Google Calendar API habilitadas
|
||||
- [ ] Gmail OAuth configurado en n8n con cuenta de envio GLM
|
||||
- [ ] Supabase project creado con las tres tablas del esquema (ver seccion de base de datos)
|
||||
- [ ] Google Sheet del calendario GLM Way accesible con la cuenta de servicio configurada
|
||||
- [ ] n8n corriendo en el servidor virtual GLM con conectividad a todos los servicios externos
|
||||
- [ ] Credenciales almacenadas en el vault de credenciales GLM — nunca en el repo
|
||||
|
||||
### Variables de entorno
|
||||
|
||||
| Variable | Descripcion | Donde se obtiene |
|
||||
|---|---|---|
|
||||
| `BAMBOOHR_API_KEY` | API Key de BambooHR | BambooHR → Account → API Keys |
|
||||
| `BAMBOOHR_SUBDOMAIN` | Subdominio de la cuenta GLM en BambooHR | URL de BambooHR: `subdomain.bamboohr.com` |
|
||||
| `GOOGLE_SERVICE_ACCOUNT_JSON` | Credenciales de la cuenta de servicio de Google Cloud | Google Cloud Console → IAM → Service Accounts |
|
||||
| `GOOGLE_CALENDAR_ID_ES` | ID del Google Calendar de la sesion GLM Way en espanol | Google Calendar → Configuracion del evento |
|
||||
| `GOOGLE_CALENDAR_ID_EN` | ID del Google Calendar de la sesion GLM Way en ingles | Google Calendar → Configuracion del evento |
|
||||
| `GLMWAY_SHEET_ID` | ID del Google Sheet del calendario de sesiones | URL del Sheet: `docs.google.com/spreadsheets/d/{ID}` |
|
||||
| `GMAIL_SENDER` | Cuenta de Gmail autorizada para envio | Definida en la configuracion OAuth de n8n |
|
||||
| `FORM_URL_ES` | Link del formulario de evaluacion en espanol | Google Forms — obtener link de respuesta |
|
||||
| `FORM_URL_EN` | Link del formulario de evaluacion en ingles | Google Forms — obtener link de respuesta |
|
||||
| `SUPABASE_URL` | URL del proyecto Supabase | Supabase → Settings → API |
|
||||
| `SUPABASE_KEY` | API Key de Supabase (service role) | Supabase → Settings → API |
|
||||
| `ALERT_EMAIL_LUIS` | Email de Luis Matos para alertas de sistema | — |
|
||||
|
||||
> NUNCA commitear credenciales al repo. Todas las keys van en el vault de credenciales GLM.
|
||||
|
||||
### Esquema de base de datos
|
||||
|
||||
```sql
|
||||
-- Tabla de inscritos por sesion
|
||||
CREATE TABLE inscritos_glmway (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
empleado_id TEXT NOT NULL,
|
||||
nombre TEXT NOT NULL,
|
||||
email TEXT NOT NULL,
|
||||
pais TEXT NOT NULL,
|
||||
idioma TEXT NOT NULL CHECK (idioma IN ('ES', 'EN')),
|
||||
cargo TEXT,
|
||||
hire_date DATE NOT NULL,
|
||||
sesion_id UUID REFERENCES sesiones_glmway(id),
|
||||
sesion_fecha DATE,
|
||||
sesion_link TEXT,
|
||||
estado TEXT DEFAULT 'notificado',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Tabla de sesiones GLM Way
|
||||
CREATE TABLE sesiones_glmway (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
fecha DATE NOT NULL,
|
||||
idioma TEXT NOT NULL CHECK (idioma IN ('ES', 'EN')),
|
||||
facilitador TEXT,
|
||||
meet_link TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Tabla de asistencia
|
||||
CREATE TABLE asistencia_glmway (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
empleado_id TEXT NOT NULL,
|
||||
sesion_id UUID REFERENCES sesiones_glmway(id),
|
||||
asistio BOOLEAN DEFAULT FALSE,
|
||||
evaluacion_completada BOOLEAN DEFAULT FALSE,
|
||||
registrado_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```js
|
||||
// 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"]
|
||||
```
|
||||
|
||||
### Instalacion / Deploy
|
||||
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`).
|
||||
|
||||
```bash
|
||||
# Clonar el repo
|
||||
git clone https://gitea.glm.com/glm-it/automatizacion-glm-way
|
||||
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).
|
||||
|
||||
# Configurar variables de entorno
|
||||
cp .env.example .env
|
||||
# Editar .env con las credenciales reales del vault GLM
|
||||
---
|
||||
|
||||
# Importar el workflow en n8n
|
||||
# n8n → Settings → Import workflow → seleccionar /n8n/workflow.json
|
||||
## 5. Flujos Detallados (10 sub-workflows en 1 workflow)
|
||||
|
||||
# Ejecutar el setup inicial de Supabase
|
||||
psql $SUPABASE_URL -f /src/db/schema.sql
|
||||
### 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 #TheGLMWay` — *Texto:* “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 #TheGLMWay` → `https://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 Trigger4` — `0 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)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Como funciona
|
||||
## 6. Diagrama de Estados del Inscrito
|
||||
|
||||
### Flujo paso a paso
|
||||
|
||||
1. **Trigger deteccion de nuevos ingresos (diario, 7am):** n8n corre un scheduler diario que consulta BambooHR buscando empleados con hire_date = fecha actual. Por cada nuevo ingreso extrae: nombre, email, pais, cargo. Clasifica el idioma segun el pais y consulta Google Sheets para obtener la proxima sesion GLM Way correspondiente.
|
||||
|
||||
2. **Notificacion D1:** El sistema envia un email al nuevo ingreso via Gmail con su nombre, la fecha y hora de su proxima sesion GLM Way, el nombre del facilitador y el link del Google Meet. Registra al empleado en la tabla inscritos_glmway con estado "notificado".
|
||||
|
||||
3. **Aviso al coordinador de RRHH (48hrs antes, scheduler diario 8am):** n8n detecta sesiones que ocurren en 48 horas, consulta en Supabase los inscritos de esa sesion por pais, identifica al coordinador de RRHH de cada pais en BambooHR y envia un email con la lista de inscritos (nombre, cargo, fecha de inicio) y el link del Meet.
|
||||
|
||||
4. **Recordatorio al nuevo ingreso (24hrs antes, scheduler diario 8am):** n8n detecta sesiones que ocurren en 24 horas y envia un email de recordatorio a cada inscrito con estado "notificado" o "recordado". Actualiza el estado a "recordado".
|
||||
|
||||
5. **Envio de formulario post-sesion (scheduler cada hora):** n8n detecta sesiones que terminaron en la ultima hora y envia el formulario de evaluacion correspondiente (ES o EN) a cada inscrito. Actualiza el estado a "evaluacion_enviada".
|
||||
|
||||
6. **Registro de asistencia:** n8n consulta Google Calendar API para obtener la lista de attendees del evento Meet de la sesion. Cruza esa lista contra los inscritos en Supabase y registra en asistencia_glmway: asistio = true/false por empleado.
|
||||
|
||||
### Schedules / Triggers
|
||||
|
||||
| Trigger | Frecuencia | Descripcion |
|
||||
|---|---|---|
|
||||
| Deteccion nuevos ingresos D1 | Cron diario 7am | Consulta BambooHR por hire_date = hoy y envia notificacion inicial |
|
||||
| Aviso coordinador RRHH | Cron diario 8am | Detecta sesiones en 48hrs y notifica al coordinador con lista de inscritos |
|
||||
| Recordatorio empleado | Cron diario 8am | Detecta sesiones en 24hrs y envia recordatorio a los inscritos |
|
||||
| Envio de evaluacion | Cron cada hora | Detecta sesiones terminadas en la ultima hora y envia formulario |
|
||||
| Registro de asistencia | Cron cada hora | Extrae attendees del Meet y cruza con inscritos en Supabase |
|
||||
```
|
||||
[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++
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
## 7. Notificaciones
|
||||
|
||||
### Como probar el sistema
|
||||
|
||||
```bash
|
||||
# Test manual en n8n — flujo completo
|
||||
# 1. Crear empleado de prueba en BambooHR con hire_date = manana
|
||||
# 2. Abrir n8n → workflow Deteccion D1 → Execute workflow
|
||||
# 3. Verificar que llega el email al empleado de prueba
|
||||
# 4. Verificar registro en Supabase: SELECT * FROM inscritos_glmway WHERE email = 'test@glm.com'
|
||||
|
||||
# Test del aviso al coordinador
|
||||
# 1. Ajustar manualmente la fecha de una sesion en Supabase a 48hrs desde ahora
|
||||
# 2. Ejecutar manualmente el workflow de aviso coordinador en n8n
|
||||
# 3. Verificar que el coordinador del pais recibe el email con la lista correcta
|
||||
|
||||
# Test del registro de asistencia
|
||||
# 1. Ejecutar manualmente el workflow post-sesion con el ID de una sesion real
|
||||
# 2. Verificar en Supabase: SELECT * FROM asistencia_glmway WHERE sesion_id = '{id}'
|
||||
```
|
||||
|
||||
### Casos de prueba minimos
|
||||
|
||||
| Caso | Input | Output esperado | Estado |
|
||||
| Destinatario | Canal | Cuándo | Formato |
|
||||
|---|---|---|---|
|
||||
| Nuevo ingreso pais hispanohablante | hire_date = hoy, pais = Colombia | Email en espanol con proxima sesion ES | A completar por Eidan |
|
||||
| Nuevo ingreso pais anglohablante | hire_date = hoy, pais = Jamaica | Email en ingles con proxima sesion EN | A completar por Eidan |
|
||||
| Aviso coordinador — pais con inscritos | Sesion en 48hrs, 2 inscritos en Supabase | Email al coordinador con lista de 2 personas | A completar por Eidan |
|
||||
| Aviso coordinador — pais sin coordinador | Sesion en 48hrs, no hay coordinador en BambooHR | Excepcion registrada en Supabase + alerta a Luis Matos | A completar por Eidan |
|
||||
| Recordatorio 24hrs | Sesion en 24hrs, inscrito con estado "notificado" | Email de recordatorio + estado actualizado a "recordado" | A completar por Eidan |
|
||||
| Formulario post-sesion | Sesion terminada hace 30 min | Email con formulario correcto segun idioma | A completar por Eidan |
|
||||
| BambooHR sin nuevos ingresos del dia | hire_date = hoy, 0 resultados | Flujo termina sin error, sin emails enviados | A completar por Eidan |
|
||||
| Google Meet sin attendees | API retorna lista vacia | Excepcion registrada, alerta a Luis Matos | A completar por Eidan |
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## Errores conocidos y troubleshooting
|
||||
## 8. Instalación y Configuración
|
||||
|
||||
| Error | Causa probable | Solucion |
|
||||
|---|---|---|
|
||||
| `401 Unauthorized` en BambooHR | API Key vencida o incorrecta | Renovar key en BambooHR → Account → API Keys y actualizar `.env` |
|
||||
| `403 Forbidden` en Google Sheets | Cuenta de servicio sin permisos sobre el Sheet | Compartir el Google Sheet con el email de la cuenta de servicio |
|
||||
| Email no llega al empleado | Gmail OAuth expirado o cuenta bloqueada | Reautenticar Gmail en n8n → Credentials |
|
||||
| Lista de attendees vacia | Google Calendar API no retorna participantes del Meet | Verificar que el evento tiene el Meet integrado y que la cuenta de servicio tiene acceso al calendario |
|
||||
| Coordinador no encontrado para un pais | El campo Posicion en BambooHR no coincide exactamente con "Coordinador de RRHH" | Revisar el valor exacto del campo en BambooHR y ajustar el filtro en n8n |
|
||||
| Timeout en n8n | Servicio externo lento (BambooHR o Google) | Aumentar el timeout del nodo en n8n → Settings → Timeout |
|
||||
### 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`
|
||||
|
||||
> Seccion a completar por Eidan con errores adicionales encontrados durante el desarrollo.
|
||||
### Importar
|
||||
1. n8n → `Import from File` → `GLMWay.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`.
|
||||
|
||||
---
|
||||
|
||||
## Monitoreo
|
||||
## 9. Operación y Monitoreo
|
||||
|
||||
### Como saber si el sistema esta funcionando
|
||||
|
||||
- **n8n Executions:** Revisar n8n → Executions diariamente. Todos los workflows deben aparecer en verde. Un workflow en rojo indica fallo.
|
||||
- **Alertas automaticas:** El sistema envia un email a Luis Matos cuando un flujo falla sin recuperarse o cuando detecta una excepcion critica (coordinador no encontrado, Meet sin attendees).
|
||||
- **Output esperado en condiciones normales:** Cada semana deben aparecer registros nuevos en inscritos_glmway y asistencia_glmway en Supabase correspondientes a la sesion de esa semana.
|
||||
- **Verificacion rapida en Supabase:**
|
||||
|
||||
```sql
|
||||
-- Ver inscritos de la semana actual
|
||||
SELECT * FROM inscritos_glmway
|
||||
WHERE created_at >= date_trunc('week', NOW());
|
||||
|
||||
-- Ver asistencia de la ultima sesion
|
||||
SELECT i.nombre, i.idioma, a.asistio, a.evaluacion_completada
|
||||
FROM asistencia_glmway a
|
||||
JOIN inscritos_glmway i ON a.empleado_id = i.empleado_id
|
||||
ORDER BY a.registrado_at DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
- **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.
|
||||
|
||||
---
|
||||
|
||||
## Estructura del repositorio
|
||||
## 10. Riesgos y Recomendaciones
|
||||
|
||||
```
|
||||
/automatizacion-glm-way
|
||||
├── README.md <- Este archivo
|
||||
├── .env.example <- Variables de entorno de ejemplo (sin valores reales)
|
||||
├── /n8n
|
||||
│ └── workflow.json <- Export del workflow completo de n8n
|
||||
├── /src
|
||||
│ └── /db
|
||||
│ └── schema.sql <- Script de creacion de tablas en Supabase
|
||||
├── /docs
|
||||
│ └── architecture.png <- Diagrama de arquitectura (agregar al cerrar el ciclo)
|
||||
├── CHANGELOG.md <- Historial de cambios (completar durante el ciclo)
|
||||
└── DECISIONS.md <- Log de decisiones tecnicas (completar durante el ciclo)
|
||||
```
|
||||
| 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 |
|
||||
|
||||
---
|
||||
|
||||
## CHANGELOG
|
||||
## 11. Archivos Relacionados
|
||||
|
||||
Formato: [YYYY-MM-DD] vX.X — Descripcion del cambio
|
||||
|
||||
```
|
||||
[2026-06-09] v0.1 — Inicio del ciclo. Setup del repo y esquema de base de datos.
|
||||
```
|
||||
|
||||
> Completar durante el ciclo con cada version funcional.
|
||||
- `GLMWay.json` — definición completa del workflow (importable en n8n)
|
||||
- `README_GLMWay.md` — este documento
|
||||
|
||||
---
|
||||
|
||||
## DECISIONS LOG
|
||||
*Documentado a partir de `GLMWay.json` v`f657df3d-e5b6-445e-ad75-df66da81ebf3` — última edición inspeccionada 27/08/2026.*
|
||||
*GomezLee Marketing — Automatización #TheGLMWay.*
|
||||
|
||||
### DEC-001 — Clasificacion de idioma por pais y no por campo de empleado
|
||||
|
||||
- Fecha: 2026-06-04
|
||||
- Contexto: Necesitabamos determinar si un empleado va a la sesion en espanol o en ingles para inscribirlo correctamente.
|
||||
- Opciones consideradas: (A) Usar un campo de idioma en el perfil de BambooHR. (B) Inferir el idioma a partir del pais del empleado.
|
||||
- Decision: Opcion B — inferir por pais.
|
||||
- Razon: BambooHR no tiene un campo de idioma estandarizado en los perfiles GLM. El pais es un campo confiable y ya disponible. Paises en ingles definidos: Jamaica, Trinidad and Tobago, Guyana, St. Croix, Aruba, St. Thomas.
|
||||
|
||||
### DEC-002 — Lectura del link de Meet desde Google Sheets en tiempo real
|
||||
|
||||
- Fecha: 2026-06-04
|
||||
- Contexto: Necesitabamos decidir si almacenar el link del Google Meet en Supabase con anticipacion o consultarlo en el momento del envio.
|
||||
- Opciones consideradas: (A) Pre-cargar el link en Supabase al crear el inscrito. (B) Consultar el Google Sheet en tiempo real al momento de cada envio.
|
||||
- Decision: Opcion B — consulta en tiempo real.
|
||||
- Razon: Los links de Google Meet pueden cambiar o actualizarse en el Sheet. Consultar en tiempo real garantiza que siempre se envia el link correcto y evita datos desactualizados en Supabase.
|
||||
|
||||
> Agregar nuevas decisiones durante el ciclo con el formato DEC-00N.
|
||||
|
||||
---
|
||||
|
||||
## Contactos del proyecto
|
||||
|
||||
| Rol | Nombre | Contacto |
|
||||
|---|---|---|
|
||||
| Product Owner | Maximo Gomez | [completar] |
|
||||
| IT Manager | Luis Matos | [completar] |
|
||||
| Developer | Eidan Then | [completar] |
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
Checklist antes de mover a Completado en Kan.bn:
|
||||
|
||||
- [ ] Todos los criterios de exito del PRD cumplidos y verificados
|
||||
- [ ] 100% de nuevos ingresos de prueba notificados sin intervencion manual
|
||||
- [ ] Coordinadores de RRHH notificados 48hrs antes con lista de inscritos correcta
|
||||
- [ ] Recordatorios enviados correctamente en pruebas de los dos idiomas
|
||||
- [ ] Registro de asistencia generado en Supabase para al menos una sesion real
|
||||
- [ ] Formularios de evaluacion enviados automaticamente post-sesion
|
||||
- [ ] Codigo commiteado y pusheado a Gitea
|
||||
- [ ] README completo y actualizado
|
||||
- [ ] Variables de entorno documentadas en `.env.example`
|
||||
- [ ] Tests basicos pasando
|
||||
- [ ] Workflow de n8n exportado en `/n8n/workflow.json`
|
||||
- [ ] Schema SQL en `/src/db/schema.sql`
|
||||
- [ ] CHANGELOG actualizado con la version final
|
||||
- [ ] Probado en ambiente real (no solo local)
|
||||
- [ ] Luis Matos valido el output
|
||||
- [ ] Maximo aprobo el resultado final
|
||||
|
||||
---
|
||||
|
||||
_Documento mantenido por el equipo GLM IT · Ultima actualizacion: 2026-06-04_
|
||||
Reference in New Issue
Block a user