diff --git a/hbdwsp-documentacion.md b/hbdwsp-documentacion.md new file mode 100644 index 0000000..f9224c5 --- /dev/null +++ b/hbdwsp-documentacion.md @@ -0,0 +1,413 @@ +# 🎂 Workflow: `hbdwsp` — Bot de Cumpleaños GLM (WhatsApp) + +**ID del Workflow:** `ZzH2eMPrsqlY7WPz` +**Autor:** Eidan Then (`ethen@gomezleemarketing.com`) +**Ăšltima actualizaciĂłn:** 12 de junio de 2026 +**VersiĂłn activa:** `2d27b5f7-f5c4-41f9-b008-d8f3a50557a5` (v251) +**Estado:** âś… Activo +**Zona horaria:** America/Santo_Domingo (UTC-04:00) + +--- + +## DescripciĂłn General + +Este workflow automatiza el envĂo de tarjetas de cumpleaños personalizadas al grupo de WhatsApp corporativo de GLM. Cada dĂa a las 10:00 AM, el sistema revisa los empleados registrados en BambooHR, filtra los que cumplen años ese dĂa, genera una tarjeta visual personalizada con su foto y la envĂa al grupo correspondiente. + +El flujo excluye automáticamente a empleados de paĂses no hispanos (Jamaica, Trinidad & Tobago, Barbados, etc.) y maneja casos donde el empleado no tiene fecha de cumpleaños o foto registrada. + +--- + +## Arquitectura del Flujo + +``` +Schedule Trigger (10am) + └── BambooHR (Reporte CSV #1509) + └── Google Drive (Guardar CSV) + └── Google Sheets (Leer datos) + └── Pais? (Filtrar hispanos) + ├── [TRUE] Obtener empleado (BambooHR) + │ └── Merge (unir datos Sheets + Bamboo) + │ └── Loop Over Items + │ └── Tiene fecha? + │ ├── [FALSE] → Wait3 → Loop (siguiente) + │ └── [TRUE] → Coincide con fecha de hoy? + │ ├── [FALSE] → Wait3 → Loop + │ └── [TRUE] → Tiene foto? + │ ├── [TRUE] → Foto Empleado URL + │ └── [FALSE] → URL si no tiene foto (bizcocho) + │ └── HTML (generar tarjeta) + │ └── HTTP Request (screenshot browserless) + │ └── Extract from File + │ └── Enviar imagen WhatsApp + │ └── Wait (3s) + │ └── Loop (siguiente) + └── [FALSE] Ignorado (paĂs no hispano) +``` + +--- + +## Nodos del Workflow + +### 1. Schedule Trigger +- **Tipo:** `scheduleTrigger` +- **ConfiguraciĂłn:** Se ejecuta todos los dĂas a las **10:00 AM** (hora Santo Domingo, UTC-4). +- **Notas:** El trigger está pinned con fecha `2026-05-29` para pruebas manuales. + +--- + +### 2. BambooHR (Reporte CSV) +- **Tipo:** `bambooHr` — `companyReport` +- **Reporte ID:** `1509` +- **Formato:** CSV +- **Credencial:** `Eidan - BambooHR account` +- **FunciĂłn:** Descarga el listado completo de empleados activos con sus datos (incluyendo Birthday, Location, EEID, Work Email). + +--- + +### 3. Google Drive (Guardar CSV) +- **Tipo:** `googleDrive` — `update` +- **Archivo destino:** `HBD.csv` (`1Jw9yOyIKB1QLcr9m8ObGP9PK0tC9z3n6`) +- **Credencial:** `Eidan - Google Drive account` +- **FunciĂłn:** Actualiza el archivo CSV en Google Drive con los datos más recientes de BambooHR. Sirve como respaldo y fuente de verdad para Google Sheets. + +--- + +### 4. Google Sheets (Leer datos) +- **Tipo:** `googleSheets` — read +- **Spreadsheet:** `HBD` (`1p0bCvHAIHjobiPhDfmTshZWvRP6PWAmmTtSoX77lBmM`) +- **Hoja:** `HBD` (gid: `759771456`) +- **Credencial:** `Eidan - Google Sheets account` +- **FunciĂłn:** Lee los datos procesados del spreadsheet. AquĂ se encuentran campos adicionales como `Location` que se usa para el filtro de paĂs. + +--- + +### 5. Pais? (Filtro de paĂs) +- **Tipo:** `if` +- **LĂłgica:** `AND` de condiciones `notEquals` +- **PaĂses excluidos (FALSE):** + - Jamaica + - Trinidad and Tobago / Trinidad & Tobago / Tobago + - Barbados + - Saint Thomas + - St. Croix +- **TRUE:** El empleado es de un paĂs hispano → el flujo continĂşa. +- **FALSE:** El empleado es de un paĂs no hispano → se ignora silenciosamente. + +--- + +### 6. Obtener empleado +- **Tipo:** `bambooHr` — `get` +- **Employee ID:** `{{ $json.EEID }}` +- **Credencial:** `Eidan - BambooHR account` +- **ConfiguraciĂłn:** `retryOnFail: true` +- **FunciĂłn:** Obtiene el perfil completo del empleado desde BambooHR, incluyendo `photoUrl` y `photoUploaded`. + +--- + +### 7. Merge +- **Tipo:** `merge` — combine (enrich) +- **Join por:** `workEmail` ↔ `Work Email` +- **Modo:** `enrichInput1` (enriquece los datos de Bamboo con los de Google Sheets) +- **FunciĂłn:** Combina en un solo objeto los datos de BambooHR (foto, cargo, etc.) con los de Google Sheets (Location, Birthday, etc.). + +--- + +### 8. Loop Over Items +- **Tipo:** `splitInBatches` +- **FunciĂłn:** Procesa cada empleado de forma individual y secuencial. Al terminar con uno, vuelve al siguiente. Cuando no quedan más Ătems, el flujo termina. + +--- + +### 9. Tiene fecha? +- **Tipo:** `if` +- **CondiciĂłn:** `!$json.Birthday` es `true` +- **TRUE (sin fecha):** → `Wait3` → vuelve al loop (siguiente empleado). +- **FALSE (tiene fecha):** → continĂşa hacia `Coincide con fecha de hoy?`. + +> ⚠️ **Nota:** La nota sticky original decĂa que el sistema avisarĂa a RRHH si falta la fecha, pero actualmente el `TRUE` solo hace un `Wait3` y continĂşa. Considerar agregar una notificaciĂłn a RRHH. + +--- + +### 10. Coincide con fecha de hoy? +- **Tipo:** `if` +- **CondiciĂłn:** `$json.Birthday` equals `$now.format('MMMM dd')` (con espacios) +- **ValidaciĂłn:** `loose` (tipos flexibles) +- **`onError`:** `continueRegularOutput` +- **TRUE:** La fecha coincide → continĂşa el flujo. +- **FALSE:** No es el cumpleaños hoy → `Wait3` → siguiente empleado. + +> ⚠️ **Importante:** El `rightValue` tiene un espacio al final: `{{ $now.format('MMMM dd') }} `. Asegurarse de que los datos de Birthday en el CSV tambiĂ©n tengan ese formato (`MMMM dd`) para evitar falsos negativos. + +--- + +### 11. Tiene foto? +- **Tipo:** `if` +- **CondiciĂłn:** `$json.photoUploaded == true` es `true` +- **TRUE:** → `Foto Empleado URL` (usa la foto real del empleado) +- **FALSE:** → `URL si no tiene foto` (usa imagen de bizcocho) + +--- + +### 12. Foto Empleado URL / URL si no tiene foto +- **Tipo:** `set` +- **Foto real:** `{{ $json.photoUrl }}` (URL de BambooHR) +- **Foto fallback:** `https://gomezleemarketing.com/wp-content/uploads/2026/03/hbdcake.png` +- **Output:** Campo `photoUrl` que se pasa al nodo HTML. + +--- + +### 13. HTML (GeneraciĂłn de tarjeta) +- **Tipo:** `html` +- **Dimensiones:** 1080 Ă— 1920 px (formato Instagram Stories / WhatsApp) +- **Background:** `https://gomezleemarketing.com/wp-content/uploads/2026/03/Comunicacion-de-Cumpleanos-Background.jpg` +- **Contenido dinámico:** + - Foto del empleado (circular, 530px) + - Nombre del empleado (`firstName`) + - Fecha de cumpleaños formateada en español (ej: "12 de junio") +- **Nota:** Los divs `.hello`, `.message`, `.position` y `.team` están vacĂos en la versiĂłn actual. Pueden ser rellenados con texto personalizado. + +--- + +### 14. HTTP Request (Screenshot) +- **Tipo:** `httpRequest` POST +- **URL:** `https://pruebadetemplate-browserless.k11ytw.easypanel.host/chromium/screenshot` +- **Token:** `8d66338953f117a7c29c55364c8c9e6d` +- **Viewport:** `1080 Ă— 1920` +- **Response format:** `file` (binario) +- **FunciĂłn:** Convierte el HTML generado en una imagen PNG usando Browserless (Chromium headless) alojado en Easypanel. + +--- + +### 15. Extract from File +- **Tipo:** `extractFromFile` — `binaryToPropery` +- **FunciĂłn:** Convierte el binario de la imagen en base64 (`data`) para enviarlo a la API de WhatsApp. + +--- + +### 16. Enviar mensaje al whatsapp imagen +- **Tipo:** `httpRequest` POST +- **URL:** `https://wsp.gomezleemarketing.com/message/sendMedia/botsoporte` +- **API Key:** `C267126ABB45-4C12-B626-6BAB1833F5D7` +- **NĂşmero destino:** `120363404268176806@g.us` (Grupo oficial Motorola) +- **Tipo de media:** `image` +- **Media:** `{{ $json.data }}` (base64) +- **Delay:** 2000ms + +--- + +### 17. Wait (entre empleados) +- **Tipo:** `wait` +- **DuraciĂłn:** 3 segundos +- **FunciĂłn:** Pausa entre el envĂo y la vuelta al loop para no saturar la API de WhatsApp. + +### Wait3 (skip al siguiente) +- **Tipo:** `wait` +- **DuraciĂłn:** 1 segundo +- **FunciĂłn:** Pequeña pausa antes de saltar al siguiente empleado cuando no cumple años o no tiene fecha. + +--- + +## Subworkflow: Respaldo en Gitea + +Este subworkflow es independiente (trigger manual) y guarda/actualiza el JSON del workflow en Gitea como respaldo de versiĂłn. + +### Nodos: +| Nodo | FunciĂłn | +|------|---------| +| `Valores` | Define `repo_name: wsp-cumpleanos` y `file_name: hbd-panama-motorola` | +| `Obtener archivo` | GET al repo Gitea para obtener el SHA actual del archivo | +| `Get a workflow1/2` | Obtiene el JSON del propio workflow (`ZzH2eMPrsqlY7WPz`) vĂa API de n8n | +| `Code in JavaScript` | Prepara payload con SHA para **actualizar** (PUT) | +| `Code in JavaScript1` | Prepara payload sin SHA para **crear** (POST) | +| `Actualizar archivo` | PUT al endpoint de Gitea (actualiza si ya existe) | +| `Subir archivo` | POST al endpoint de Gitea (crea si no existe) | + +**Repositorio:** `https://git.digitalcompass.agency/EidanThen/wsp-cumpleanos` + +--- + +## Requisitos de InstalaciĂłn + +### Servicios externos requeridos + +| Servicio | Uso | Credencial | +|----------|-----|------------| +| **BambooHR** | Fuente de datos de empleados | `Eidan - BambooHR account` | +| **Google Drive** | Almacenamiento del CSV actualizado | `Eidan - Google Drive account` | +| **Google Sheets** | Lectura de datos procesados | `Eidan - Google Sheets account` | +| **Browserless** (Easypanel) | Renderizado HTML → PNG | Token en URL | +| **EvolutionAPI** (WhatsApp) | EnvĂo de imágenes al grupo | API Key en header | +| **Gitea** (opcional) | Respaldo del workflow JSON | `Eidan - gitea` | +| **n8n API** (opcional) | Leer JSON del workflow para backup | `Eidan - n8n account` | + +--- + +### Paso 1: Configurar credenciales en n8n + +1. Ve a **Settings → Credentials** en n8n. +2. Crea las siguientes credenciales: + +#### BambooHR +- **Tipo:** BambooHR API +- **API Key:** (tu API key de BambooHR) +- **Subdomain:** `gomezleemarketing` + +#### Google Drive / Sheets +- **Tipo:** Google OAuth2 +- Autoriza con la cuenta `ethen@gomezleemarketing.com` +- Aplica a ambos nodos (Drive y Sheets) + +#### Gitea (Header Auth) +- **Tipo:** Header Auth +- **Name:** `Authorization` +- **Value:** `token TU_TOKEN_GITEA` + +--- + +### Paso 2: Configurar Google Sheets + +El spreadsheet `HBD` debe tener al menos las columnas: + +| Columna | DescripciĂłn | +|---------|-------------| +| `EEID` | ID del empleado en BambooHR | +| `Work Email` | Email corporativo (clave de join con Bamboo) | +| `Birthday` | Fecha en formato `MMMM dd` (ej: `June 12`) | +| `Location` | PaĂs del empleado (ej: `Dominican Republic`) | +| `firstName` | Nombre del empleado | + +--- + +### Paso 3: Configurar Browserless + +El workflow usa una instancia de Browserless alojada en Easypanel: + +``` +URL: https://pruebadetemplate-browserless.k11ytw.easypanel.host +Token: 8d66338953f117a7c29c55364c8c9e6d +``` + +Si se despliega una nueva instancia, actualizar la URL y el token en el nodo **HTTP Request** (screenshot). + +**Para desplegar Browserless en Docker:** +```yaml +services: + browserless: + image: ghcr.io/browserless/chromium:latest + ports: + - "3000:3000" + environment: + - TOKEN=tu_token_aqui +``` + +--- + +### Paso 4: Configurar EvolutionAPI (WhatsApp) + +El workflow usa EvolutionAPI como intermediario para WhatsApp: + +- **Base URL:** `https://wsp.gomezleemarketing.com` +- **Instancia:** `botsoporte` +- **API Key:** configurada en el header `apikey` + +AsegĂşrate de que la instancia `botsoporte` estĂ© conectada y activa antes de ejecutar el workflow. + +--- + +### Paso 5: Importar el workflow en n8n + +1. En n8n, ve a **Workflows → Import from file/URL**. +2. Pega el JSON del workflow o importa desde Gitea. +3. Asigna las credenciales correctas a cada nodo. +4. Activa el workflow con el toggle. + +--- + +## ConfiguraciĂłn del Grupo de WhatsApp + +| Entorno | NĂşmero del grupo | +|---------|-----------------| +| **ProducciĂłn (Motorola)** | `120363404268176806@g.us` | +| **Pruebas** | `120363426353723539@g.us` | + +Para cambiar el grupo destino, editar el campo `number` en el nodo **Enviar mensaje al whatsapp imagen**. + +--- + +## PersonalizaciĂłn de la Tarjeta HTML + +La tarjeta visual se genera en el nodo `HTML`. Los siguientes divs están disponibles para personalizaciĂłn: + +```html +