Docs

Communication Workflows

Sistema de workflows automatizados para comunicaciones multicanal: triggers, ejecución, filtrado de destinatarios, reintentos y ciclo de vida de mensajes.

PublicadoMarzo 2026Equipo de desarrollo, arquitectos, stakeholders

Modelo CommunicationWorkflow

El modelo CommunicationWorkflow representa una regla de automatizacion que define cuando, a quien y que mensaje enviar. Cada workflow pertenece a un evento específico y se ejecuta automáticamente cuando se cumple su condición de trigger.

Campos del Modelo

CampoTipoDescripción
idUUIDIdentificador único del workflow
eventIdUUIDEvento al que pertenece el workflow
namestringNombre descriptivo del workflow (ej: "Recordatorio 7 días antes")
triggerenumEvento que dispara la ejecución
triggerConfigJSONConfiguración del trigger (ej: { daysOffset: 7 })
campaignTypeenumTipo de campana que se crea al ejecutarse
channelstringCanal de comunicación (email, whatsapp, sms, push)
subjectstringAsunto del mensaje (para email)
bodystringCuerpo del mensaje con variables de template
templateIdUUID (opcional)Referencia a un template de comunicación predefinido
recipientFilterJSONFiltros para seleccionar destinatarios (estado RSVP, grupo, tags)
statusenumEstado actual del workflow
executionCountnumberVeces que se ha ejecutado exitosamente
lastExecutedAtdatetimeFecha y hora de la última ejecución
createdAtdatetimeFecha de creación
updatedAtdatetimeUltima modificación

CommunicationWorkflowStatus

EstadoDescripción
ACTIVEEl workflow se ejecutara cuando ocurra su trigger
PAUSEDEl workflow está temporalmente deshabilitado; no se ejecutara aunque ocurra el trigger
COMPLETEDEl workflow ha terminado su ciclo (aplica a triggers que solo se ejecutan una vez, como EVENT_DAY)

CommunicationWorkflowTrigger

TriggerCategoríaDescripción
GUEST_ADDEDEvento de dominioSe dispara al agregar un invitado nuevo al evento
RSVP_CONFIRMEDEvento de dominioSe dispara cuando un invitado confirma asistencia
RSVP_DECLINEDEvento de dominioSe dispara cuando un invitado declina la invitación
DAYS_BEFORE_EVENTProgramadoSe ejecuta N días antes de la fecha del evento
EVENT_DAYProgramadoSe ejecuta el día del evento
POST_EVENTProgramadoSe ejecuta después del evento (agradecimiento, encuestas, etc.)

Controller y Servicio

CommunicationWorkflowsController

El controller expone endpoints CRUD protegidos por la cadena estandar de guards (ClerkAuthGuard + UserThrottlerGuard + RoleGuard) y requiere acceso al evento (@RequireEventAccess()).

MetodoRutaDescripciónValidaciones
GET/communication-workflows?eventId=xxxListar workflows del eventoeventId requerido, acceso al evento
POST/communication-workflowsCrear workflowMáximo 10 por evento, trigger valido, channel válido
PATCH/communication-workflows/:idActualizar workflowSolo si status es ACTIVE o PAUSED
DELETE/communication-workflows/:idEliminar workflowSolo si no tiene ejecuciones en progreso
PATCH/communication-workflows/:id/toggleAlternar entre ACTIVE y PAUSEDNo aplica a COMPLETED

CommunicationWorkflowsService

El servicio implementa la lógica de negocio para la gestión de workflows:

  • create() — Valida que no se exceda el limite de 10 workflows por evento, verifica que el trigger y canal sean validos, y crea el registro en base de datos. Si el trigger es programado (DAYS_BEFORE_EVENT, EVENT_DAY, POST_EVENT), registra el cron job correspondiente en Bull.
  • update() — Permite modificar nombre, trigger, canal, template, filtros y cuerpo del mensaje. Si cambia el trigger, actualiza o recrea el cron job.
  • toggle() — Alterna el status entre ACTIVE y PAUSED. Un workflow pausado no se ejecuta aunque ocurra su trigger. No se puede alternar un workflow COMPLETED.
  • delete() — Elimina el workflow y cancela cualquier cron job asociado. Si hay una campana en progreso generada por este workflow, la ejecución actual se completa pero no se generaran nuevas.

Tipos de Triggers

Los triggers se dividen en dos categorías fundamentales según su mecanismo de activación: triggers basados en eventos de dominio y triggers basados en tiempo.

Triggers de Evento de Dominio

Estos triggers reaccionan a acciones que ocurren en el sistema en tiempo real. Cuando un evento de dominio se emite (por ejemplo, un invitado confirma asistencia), el WorkflowEventListenerService evalua todos los workflows activos del evento correspondiente para determinar cuales deben ejecutarse.

GUEST_ADDED: Se ejecuta inmediatamente cuando se agrega un nuevo invitado al evento. Es útil para enviar automáticamente la invitación o un mensaje de bienvenida al invitado recien agregado. El destinatario es siempre el invitado que acaba de ser agregado (no requiere filtro).

RSVP_CONFIRMED: Se ejecuta cuando un invitado confirma su asistencia via el formulario RSVP de la invitación. Permite enviar automáticamente un mensaje de confirmación con detalles del evento (ubicación, horario, dress code). El destinatario es el invitado que confirmo.

RSVP_DECLINED: Se ejecuta cuando un invitado declina la invitación. Puede usarse para enviar un mensaje de agradecimiento o solicitar feedback. El destinatario es el invitado que declino.

Triggers Programados (Time-based)

Estos triggers se ejecutan en momentos específicos relativos a la fecha del evento. Utilizan un scheduler basado en Bull/Redis que ejecuta un cron job a medianoche en la zona horaria del evento. El cron job evalua si algún workflow programado debe dispararse ese día.

DAYS_BEFORE_EVENT: Requiere triggerConfig.daysOffset (número entero positivo). El workflow se ejecuta N días antes de la fecha del evento. Ejemplo: con daysOffset: 7, si el evento es el 15 de abril, el workflow se ejecuta el 8 de abril. Es el trigger más común para recordatorios.

EVENT_DAY: Se ejecuta el mismo día del evento. No requiere configuración adicional. Es útil para enviar un mensaje de "nos vemos hoy" con los ultimos detalles logisticos (direccion, estacionamiento, etc.). Después de ejecutarse, el workflow transiciona automáticamente a COMPLETED.

POST_EVENT: Se ejecuta después del evento. Puede configurarse con triggerConfig.daysOffset para específicar cuantos días después. Es útil para mensajes de agradecimiento, encuestás de satisfacción o compartir fotos de la galería. Después de ejecutarse, transiciona a COMPLETED.

Condiciones Adicionales por Trigger

Cada trigger puede tener condiciones adicionales definidas en el campo recipientFilter del workflow:

CondicionAplica aDescripción
rsvpStatusDAYS_BEFORE_EVENT, EVENT_DAY, POST_EVENTFiltrar por estado RSVP (confirmed, pending, declined)
guestGroupTodosFiltrar por grupo de invitados
tagsTodosFiltrar por tags asignados al invitado
hasPhoneWhatsApp, SMSSolo invitados con número de teléfono
hasEmailEmailSolo invitados con email
hasPushTokenPushSolo invitados con token de push registrado

Flujo de Ejecución

El flujo de ejecución de un workflow sigue una cadena de servicios con responsabilidades bien definidas. El flujo varia según el tipo de trigger.

Flujo para Triggers de Evento de Dominio

Flujo para Triggers Programados

Componentes del Flujo

ComponenteResponsabilidad
WorkflowEventListenerServiceEscucha eventos de dominio (NestJS EventEmitter). Filtra workflows activos del evento correspondiente que coinciden con el trigger emitido.
WorkflowSchedulerServiceCron job que se ejecuta diariamente. Calcula que workflows programados deben dispararse basandose en la fecha del evento y el daysOffset. Respeta la timezone del evento.
WorkflowExecutorServiceOrquestá la ejecución de un workflow: obtiene destinatarios, invoca el dispatcher, actualiza contadores. Es la pieza central que conecta la detección del trigger con el envio real.
RecipientFilterServiceAplica los filtros del recipientFilter del workflow sobre la lista de invitados del evento. Valida que cada destinatario tenga los datos de contacto necesarios para el canal elegido.
MessageDispatcherServiceCrea la CommunicationCampaign, renderiza el template con los datos de cada invitado, crea los registros CommunicationMessage y encola los jobs en Bull.

Filtrado de Destinatarios

El RecipientFilterService es responsable de determinar que invitados reciben el mensaje de un workflow. Combina múltiples criterios de filtrado con lógica AND (todos los filtros deben cumplirse).

Criterios de Filtrado

Por estado RSVP: El filtro rsvpStatus acepta uno o varios estados: CONFIRMED, PENDING, DECLINED, NO_RESPONSE. Esto permite, por ejemplo, enviar un recordatorio solo a invitados que aun no han respondido (PENDING + NO_RESPONSE).

Por grupo de invitados: El filtro guestGroup acepta uno o varios IDs de grupo. Los grupos son categorías definidas por el organizador (familia del novio, amigos de la novia, compañeros de trabajo, etc.).

Por tags: El filtro tags acepta uno o varios tags. Los tags son etiquetas libres asignadas a invitados para segmentacion flexible.

Por datos de contacto: El servicio valida automáticamente que el destinatario tenga el dato de contacto necesario para el canal del workflow:

  • Email: requiere campo email no vacio
  • WhatsApp/SMS: requiere campo phone no vacio
  • Push: requiere al menos un pushToken registrado en el dispositivo

Los invitados que no tienen el dato de contacto requerido se excluyen silenciosamente (no generan error, simplemente no reciben el mensaje).

Ejemplo de recipientFilter

{
  "rsvpStatus": ["PENDING", "NO_RESPONSE"],
  "guestGroup": ["family-bride"],
  "tags": ["vip"]
}

Este filtro selecciona invitados que: (1) no han respondido al RSVP, (2) pertenecen al grupo "familia de la novia", y (3) tienen el tag "vip". Los tres criterios deben cumplirse simultaneamente.


Integración con Sistema de Notificaciones

Los workflows reutilizan la arquitectura de 3 capas de notificaciones existente en Nvito. No implementan su propio sistema de envio, sino que generan campanas y mensajes que fluyen a traves de la infraestructura ya probada.

Arquitectura de 3 Capas

Capa 1 — NotificationChannelsModule (canales puros): Servicios de envio sin lógica de negocio. Cada servicio sabe como enviar un mensaje por su canal específico. No tienen dependencia a Bull ni a la base de datos.

  • EmailService — Envio via SMTP (nodemailer). Soporta HTML templates con variables.
  • WhatsAppService — Envio via Twilio API. Soporta templates aprobados de WhatsApp Business.
  • SmsService — Envio via Twilio API. Mensajes de texto plano.
  • PushSenderService — Envio via Expo Push API. Notificaciones push a iOS y Android.

Capa 2 — QueueModule (colas Bull/Redis): Maneja el encolamiento y procesamiento asincrono de jobs. Cada canal tiene su propia cola con concurrencia y reintentos configurables.

  • EmailProcessor — Procesa jobs de email. Concurrencia configurable.
  • WhatsAppProcessor — Procesa jobs de WhatsApp. Concurrencia limitada por rate limits de Twilio.
  • PushProcessor — Procesa jobs de push. Batch de hasta 100 notificaciones por request a Expo.

Capa 3 — NotificationsModule (API de alto nivel): Expone la API pública que los workflows (y otros módulos) consumen. Maneja la lógica de creación de campanas, mensajes, templates y metricas.

Vinculacion Workflow-Campana

Cada vez que un workflow se ejecuta, crea una nueva CommunicationCampaign con el campo workflowId vinculado. Esto permite:

  • Rastrear cuantas campanas ha generado un workflow
  • Ver el historial de envios por workflow en el panel admin
  • Distinguir campanas manuales (sin workflowId) de campanas automatizadas

Retry Policy y Ciclo de Vida de Mensajes

Ciclo de Vida del CommunicationMessage

Cada mensaje individual creado por un workflow sigue un ciclo de vida con estados bien definidos:

Estados del Mensaje

EstadoDescripciónSiguiente paso
PENDINGMensaje creado, aun no encoladoSe encola en Bull
QUEUEDJob activo en la cola BullProcesador lo toma y envia
SENTEl proveedor (SMTP, Twilio, Expo) acepto el mensajeEspera webhook de confirmación
DELIVEREDWebhook confirma que el destinatario recibio el mensajePara email, puede transicionar a OPENED
OPENEDEl destinatario abrio el email (tracking pixel)Estado terminal exitoso
FAILEDError irrecuperable después de agotar reintentosEstado terminal de error
BOUNCEDEl email reboto (direccion invalida, buzon lleno, etc.)Estado terminal, se registra para exclusion

Politica de Reintentos

Los workflows utilizan la misma politica de reintentos que el sistema de colas general:

ParametroValorDescripción
Intentos máximos3Numero total de intentos (1 original + 2 reintentos)
BackoffExponencialEl delay se duplica en cada reintento
Delay base5,000msPrimer reintento a los 5 segundos
Delay máximo60,000msTope de 1 minuto entre reintentos

La secuencia de reintentos es: intento 1 (inmediato) -> fallo -> espera 5s -> intento 2 -> fallo -> espera 10s -> intento 3 -> fallo -> dead letter.

Dead letter: Cuando un mensaje agota sus 3 intentos, su status se actualiza a FAILED y se registra el error completo en el campo errorDetails del CommunicationMessage. No se reintenta más. El contador failedCount de la campana padre se incrementa.

Webhooks de Estado

Para email y WhatsApp, los proveedores notifican cambios de estado via webhooks:

  • Email (SMTP): Los servidores SMTP con soporte de DSN (Delivery Status Notification) envian bounces. Los emails con tracking pixel reportan apertura via webhook a /api/communications/webhook/email.
  • WhatsApp (Twilio): Twilio envia callbacks de estado (sent, delivered, read, failed) al webhook configurado en /api/communications/webhook/whatsapp.
  • Push (Expo): Expo retorna tickets de recibo que se verifican periodicamente. Los tokens invalidos se marcan para exclusion.

Limites y Restricciones

Limites por Evento

LimiteValorMotivo
Workflows máximos por evento10Evitar complejidad excesiva y conflictos entre workflows
Ejecuciones simultaneas1 por workflowUn workflow no puede ejecutarse si ya tiene una ejecución en progreso
Destinatarios por ejecuciónSin limite explicitoLimitado indirectamente por la capacidad de las colas Bull

Restricciones de Negocio

  • Un workflow solo puede pertenecer a un evento. No existe el concepto de workflow global o de organización.
  • Los workflows programados (DAYS_BEFORE_EVENT, EVENT_DAY, POST_EVENT) se calculan en la timezone del evento, no UTC.
  • Un workflow PAUSED no se ejecuta, pero no pierde su posición en el scheduler. Al reactivarlo, se ejecutara en la proxima ventana valida.
  • Los workflows COMPLETED no pueden reactivarse. Para repetir un workflow completado, el usuario debe crear uno nuevo.
  • Los triggers GUEST_ADDED, RSVP_CONFIRMED y RSVP_DECLINED pueden ejecutarse múltiples veces (una por cada invitado que dispare el evento). Los triggers EVENT_DAY y POST_EVENT se ejecutan una sola vez.

Testing

El sistema de workflows cuenta con tests unitarios que cubren el servicio, controller, listener, executor, filtro y dispatcher.

Areas Cubiertas

CommunicationWorkflowsService:

  • CRUD completo (crear, listar, actualizar, eliminar)
  • Validación de limite de 10 workflows por evento
  • Toggle entre ACTIVE y PAUSED
  • Rechazo de toggle en workflows COMPLETED

CommunicationWorkflowsController:

  • Autorización: requiere token válido y acceso al evento
  • Validación de DTOs con class-validator
  • Respuestas correctas para cada endpoint

WorkflowEventListenerService:

  • Detección correcta de triggers por tipo de evento de dominio
  • Filtrado de workflows ACTIVE (ignora PAUSED y COMPLETED)
  • Manejo de múltiples workflows para el mismo trigger

WorkflowExecutorService:

  • Ejecución completa del flujo (filtrado -> dispatch -> contadores)
  • Incremento de executionCount y lastExecutedAt
  • Transición a COMPLETED para triggers de ejecución unica

RecipientFilterService:

  • Filtrado por rsvpStatus, guestGroup, tags
  • Exclusion de destinatarios sin datos de contacto
  • Combinacion AND de múltiples filtros

MessageDispatcherService:

  • Creación de CommunicationCampaign con workflowId
  • Renderizado de template con variables de invitado
  • Encolamiento correcto en el canal correspondiente

Referencias

Modulo de Workflows

  • CommunicationWorkflowsController: src/modules/communications/controllers/communication-workflows.controller.ts
  • CommunicationWorkflowsService: src/modules/communications/services/communication-workflows.service.ts
  • WorkflowEventListenerService: src/modules/communications/services/workflow-event-listener.service.ts
  • WorkflowExecutorService: src/modules/communications/services/workflow-executor.service.ts
  • WorkflowSchedulerService: src/modules/communications/services/workflow-scheduler.service.ts

Servicios Compartidos

  • RecipientFilterService: src/modules/communications/services/recipient-filter.service.ts
  • MessageDispatcherService: src/modules/communications/services/message-dispatcher.service.ts
  • CommunicationTemplateService: src/modules/communications/services/communication-template.service.ts

Modelo Prisma

  • CommunicationWorkflow: prisma/schema.prisma (modelo CommunicationWorkflow)
  • CommunicationCampaign: prisma/schema.prisma (modelo CommunicationCampaign)
  • CommunicationMessage: prisma/schema.prisma (modelo CommunicationMessage)

Documentación Relacionada

Esta pagina fue util?