Docs

Sistema de Eventos

Tabla de Contenidos

  1. Maquina de Estados
  2. Tipos de Evento
  3. Servicios por Evento
  4. Paquetes
  5. Gestion de Invitados
  6. RSVP
  7. Mesas y Asientos
  8. QR Passes y Check-in
  9. Acceso App Movil
  10. Mesa de Regalos y Hospedaje
  11. Colaboradores

1. Maquina de Estados

Cada evento transita por un ciclo de vida controlado por EventStatus. Las transiciones se validan en EventLifecycleService y mediante guards de NestJS.

Transiciones y validaciones

TransicionTriggerEfecto colateral
DRAFT -> ACTIVEInvitacion aprobada y publicadaSe registra activatedAt y auditoria
ACTIVE -> COMPLETEDCron diario (medianoche, America/Mexico_City)Invitaciones PUBLISHED/UNPUBLISHED -> CLOSED
DRAFT -> CANCELLEDPOST /events/:id/cancelSe registra cancelledAt y cancellationReason
ACTIVE -> CANCELLEDPOST /events/:id/cancelInvitaciones activas pasan a CLOSED

Campos de auditoria

CampoTipoDescripcion
activatedAtDateTimeFecha en que el evento paso a ACTIVE
cancelledAtDateTimeFecha de cancelacion
completedAtDateTimeFecha de auto-completado por cron
statusChangedByUUIDUsuario que realizo el cambio de estado
cancellationReasonStringRazon proporcionada al cancelar

2. Tipos de Evento

El modelo EventType es un catalogo dinamico en base de datos. Cada tipo define un slug, icon y un arreglo JSON defaultSections con la estructura [{ "type": "Hero", "order": 0 }, ...] que precarga secciones al crear una invitacion.

#SlugNombreSecciones por defecto
1weddingBodaHero, Couple, Itinerary, Location, RSVP
2xv-anosXV AnosHero, Quinceañera, Itinerary, Location, RSVP
3baptismBautizoHero, Details, Location, RSVP, Gallery
4birthdayCumpleanosHero, Details, Location, RSVP, Gallery
5first-communionPrimera ComunionHero, Details, Location, RSVP, Gallery
6baby-showerBaby ShowerHero, Details, Location, RSVP, GiftRegistry
7graduationGraduacionHero, Details, Location, RSVP, Gallery
8corporateEvento CorporativoHero, Details, Itinerary, Location, RSVP
9otherOtroHero, Details, Location, RSVP

3. Servicios por Evento

Nvito utiliza un sistema modular de 18 servicios controlado por EventServiceType. Cada evento tiene un EventServiceConfig con el array enabledServices y un JSON serviceSettings para configuracion granular (ej: { "GALLERY": { "maxPhotos": 50 } }).

CategoriaServicioClave
CoreInvitacion digitalINVITATION
CoreUbicaciones con GPSLOCATIONS
InvitadosLista de invitadosGUEST_LIST
InvitadosConfirmaciones (RSVP)RSVP
InvitadosGrupos de invitadosGUEST_GROUPS
Dia del eventoItinerario / timelineITINERARY
Dia del eventoAsignacion de mesasTABLES
Dia del eventoPases QR de entradaQR_PASSES
Dia del eventoCheck-in con camara QRCHECK_IN
MediaGaleria de fotosGALLERY
MediaLibro de audio (mensajes de voz)AUDIO_GUESTBOOK
MediaFotos subidas por invitadosGUEST_UPLOADS
DisenoDominio personalizadoCUSTOM_DOMAIN
DisenoMusica de fondoBACKGROUND_MUSIC
ExtrasMesa de regalosGIFT_REGISTRY
ExtrasHospedaje y transporteACCOMMODATION
ContenidoPadrinos / Corte de HonorSPONSORS
ContenidoOracion / seccion religiosaPRAYER
ContenidoAgradecimientosTHANK_YOU
ContenidoCodigo de vestimentaDRESS_CODE

Los servicios INVITATION y LOCATIONS son core y siempre estan activos. El resto se habilita segun el paquete contratado o configuracion manual.


4. Paquetes

Los paquetes son un catalogo dinamico (ServicePackage) administrado por el Super Admin. Al asignar un paquete, sus services se copian al enabledServices del evento, permitiendo personalizacion posterior.

PaquetePrecioIncluye
Essential$1,499 MXNInvitacion, ubicaciones, lista de invitados, RSVP, grupos
Plus$2,999 MXNEssential + itinerario, galeria, mesa de regalos, hospedaje, musica
VIP$4,999 MXNPlus + mesas, QR passes, check-in, subidas, libro de audio, dominio
Elite$9,999 MXNLos 18 servicios sin restriccion
PersonalizadoCotizacionSeleccion manual de servicios individuales

Modelo ServicePackage

CampoTipoDescripcion
slugVARCHAR(50) UNIQUEIdentificador unico del paquete
name / displayNameVARCHAR(100)Nombre interno y nombre visible en la UI
priceDECIMAL(10,2)Precio referencial del paquete
currencyVARCHAR(3)Moneda (default: MXN)
servicesEventServiceType[]Servicios incluidos en el paquete
colorVARCHAR(20)Color de presentacion en la UI
isRecommendedBOOLEANMarcado como recomendado
isActiveBOOLEANSi el paquete esta disponible
sortOrderINTOrden de visualizacion

5. Gestion de Invitados

El controlador GuestsController expone CRUD completo con autorizacion RBAC y soporte de importacion masiva por CSV.

Endpoints

MetodoRutaPermiso
POST /guestsCrear invitadoguests:create:assigned
POST /guests/importImportar CSVguests:import:assigned
GET /guests/event/:eventIdListar (paginado)guests:read:assigned
GET /guests/event/:eventId/dietaryResumen dieteticoguests:read:assigned
GET /guests/:idDetalleguests:read:assigned
PATCH /guests/:idActualizarguests:update:assigned
DELETE /guests/:idSoft deleteguests:delete:assigned

Campos principales del Guest

firstName, lastName, email (unico por evento), phone, groupId (FK a GuestGroup), groupSize, status (GuestStatus), dietaryRestrictions (array de DietaryRestriction), allergyInformation, mobilityNeeds, tags, metadata (JSON).

Estados del invitado (GuestStatus)

EstadoDescripcion
PENDINGRegistrado, sin respuesta RSVP
CONFIRMEDConfirmo asistencia
DECLINEDDeclino la invitacion
ATTENDEDAsistio al evento (check-in registrado)

Importacion CSV

El servicio CsvImportService procesa archivos CSV subidos via multipart/form-data. Retorna un ImportResult con total procesados, exitosos y errores por fila.

Grupos (GuestGroup)

Permiten organizar invitados en categorias (ej: "Familia del novio"). Campos: name, description, color (hex). Un invitado pertenece a un solo grupo opcional.

Restricciones alimentarias

Enum DietaryRestriction: VEGETARIAN, VEGAN, GLUTEN_FREE, HALAL, KOSHER, NUT_FREE, DAIRY_FREE, OTHER.


6. RSVP

El RSVP es un endpoint publico (sin autenticacion) para que los invitados confirmen asistencia. La consulta y estadisticas requieren autenticacion.

Diagrama de secuencia

Endpoints

MetodoRutaAuth
POST /rsvpCrear/actualizar RSVPPublico
GET /rsvp/event/:eventIdListar RSVPsAutenticado
GET /rsvp/event/:eventId/statsEstadisticasAutenticado

Estados (RSVPStatus)

PENDING (sin respuesta), CONFIRMED (asistira), DECLINED (no asistira), MAYBE (posible asistencia).

Modelo RSVP - campos clave

guestId, invitationId, status, attendeesCount, dietaryInfo (JSON con restricciones), message, respondedAt, ipAddress, userAgent, rsvpOpenedAt, responseTime (segundos), remindersSentCount.

El campo dietaryInfo sigue el formato: { "vegetarian": 1, "vegan": 0, "allergies": ["nuts"] }. El campo remindersSentCount permite rastrear recordatorios automaticos enviados a invitados con status PENDING.


7. Mesas y Asientos

El servicio TABLES permite planificar la distribucion fisica de invitados.

EventTable

Campos: name (ej: "Mesa Principal"), capacity (default 10), shape (TableShape), positionX/positionY (coordenadas en el plano), metadata (JSON).

Formas (TableShape): ROUND (defecto), SQUARE, RECTANGLE, OVAL.

TableAssignment

Asigna un invitado a una mesa con asiento opcional. La restriccion UNIQUE en guestId garantiza que cada invitado solo puede estar en una mesa. Campos: tableId, guestId, seatNumber (opcional).

Acceso Mobile (read-only)

El anfitrion (HOST) puede visualizar la distribucion y asignacion de mesas desde la app movil en modo lectura. La app ofrece dos vistas: Lista (cards con barra de ocupacion) y Plano visual (pinch-to-zoom, mismas coordenadas que el admin web). La gestion completa de mesas (crear, editar, asignar invitados, redistribuir) se realiza exclusivamente desde el admin web.

Endpoints mobile: GET /v1/mobile/events/:eventId/tables (lista con asignaciones) y GET /v1/mobile/events/:eventId/tables/stats (estadisticas de ocupacion).


8. QR Passes y Check-in

Modelo QRPass

Cada invitado puede tener pases QR vinculados al evento. Campos: code (VARCHAR UNIQUE), type (default "entry"), isUsed, usedAt, scannedBy, expiresAt, attendeesCheckedIn (para check-in parcial).

Flujo de check-in

  1. Generacion - Al habilitar QR_PASSES, se genera un QRPass por invitado con codigo unico.
  2. Distribucion - El QR se incluye en la invitacion digital o se envia por separado.
  3. Escaneo - El servicio CHECK_IN proporciona una vista con camara QR.
  4. Validacion - La API verifica existencia, expiracion y uso previo del codigo.
  5. Registro - Se marca isUsed = true, se registra usedAt/scannedBy, el invitado cambia a ATTENDED.
  6. Check-in parcial - attendeesCheckedIn permite registrar llegadas parciales del grupo.

9. Acceso App Movil

El modulo de Acceso App Movil permite a los organizadores generar codigos de acceso para que los anfitriones (HOST) inicien sesion en la app movil y gestionen el evento el dia del evento (check-in, estadisticas, invitados).

Modelo EventAccessCode

Cada codigo de acceso vincula un evento con credenciales de autenticacion movil. Campos principales:

CampoTipoDescripcion
idUUID PKIdentificador unico
eventIdUUID FKEvento al que pertenece
codeVARCHAR(8) UNIQUECodigo alfanumerico de 8 caracteres (ej: KWZDR4VD)
pinVARCHAR(255)PIN de 6 digitos hasheado con bcrypt (salt rounds: 10)
roleMobileRoleRol del acceso (default: HOST)
isActiveBOOLEANSi el codigo esta activo
expiresAtDateTime?Fecha de expiracion opcional
createdAtDateTimeFecha de creacion
updatedAtDateTimeUltima actualizacion

Flujo de gestion de codigos

  1. Prerequisito — El evento debe estar en estado ACTIVE (invitacion publicada). No se pueden generar codigos para eventos en DRAFT, CANCELLED o COMPLETED.
  2. Generacion — Desde la pagina "Acceso App Movil" en nvito-admin, el organizador genera un codigo. Se crea un EventAccessCode con codigo alfanumerico aleatorio y PIN de 6 digitos.
  3. Reveal unico del PIN — El PIN se muestra una sola vez en un dialog persistente al crear o regenerar. Se almacena hasheado con bcrypt y no puede recuperarse.
  4. Distribucion — El organizador comparte el codigo y PIN con el anfitrion (por cualquier medio externo).
  5. Login — El anfitrion ingresa codigo + PIN en la app movil. El API valida con bcrypt.compare() y crea una MobileSession.
  6. Gestion — Desde el admin se puede: activar/desactivar, regenerar PIN (genera uno nuevo), o eliminar el codigo.

Limite de codigos activos

Maximo 3 codigos activos simultaneos por evento (MAX_ACTIVE_CODES = 3). Los codigos inactivos o eliminados no cuentan contra este limite.

Seguridad

  • PIN hasheado: Se almacena con bcrypt.hash(pin, 10), nunca en texto plano
  • One-time reveal: El PIN solo es visible al crear o regenerar — no se puede consultar despues
  • Validacion de estado: El backend rechaza la creacion si el evento no esta en estado ACTIVE (ValidationException, HTTP 400)
  • Separacion de auth: El sistema de autenticacion movil es independiente de Clerk (admin web)

Endpoints (admin)

MetodoRutaDescripcion
GET/events/:eventId/access-codesListar codigos del evento (sin PIN)
POST/events/:eventId/access-codesCrear codigo con PIN auto-generado
PATCH/events/:eventId/access-codes/:codeIdActivar/desactivar codigo
POST/events/:eventId/access-codes/:codeId/regenerate-pinRegenerar PIN
DELETE/events/:eventId/access-codes/:codeIdEliminar codigo

Panel de administracion (nvito-admin)

La pagina /events/[eventId]/mobile-access muestra:

  • Badge de conteo: Codigos activos vs maximo permitido
  • Tarjetas por codigo: Codigo visible con boton copiar, estado (activo/inactivo/expirado), fecha de creacion
  • Menu de acciones: Regenerar PIN, activar/desactivar, eliminar
  • Bloqueo por estado: Si el evento no esta activo, se muestra un StatusAlert con mensaje contextual y las acciones se deshabilitan

10. Mesa de Regalos y Hospedaje

Mesa de Regalos (GiftRegistry)

Configuracion por evento con: message, note, y un fondo en efectivo (cashFundEnabled, cashFundGoal en centavos, cashFundCurrent, cashFundPaymentMethods).

Items (GiftRegistryItem): Enlaces a tiendas con type (GiftRegistryType: AMAZON, LIVERPOOL, PALACIO_HIERRO, SANBORNS, COPPEL, SEARS, OTHER), storeName, registryUrl, logoUrl.

Tambien soporta cuentas bancarias (GiftBankAccount) para transferencias directas.

Hospedaje (Accommodation)

Configuracion por evento con: message, travelTips, travelParkingInfo, travelNearestAirport.

Hoteles (AccommodationHotel): name, address, phone, distance, websiteUrl, bookingUrl (reservacion directa).

Transporte (AccommodationTransportOption): Opciones con type (Uber/DiDi, Taxi, Autobus), description, icon.


11. Colaboradores

El sistema permite invitar usuarios para co-gestionar un evento mediante EventCollaboratorInvitation.

Modelo

Campos: email, role (RoleType), invitedBy, status (CollaboratorInvitationStatus), token (UNIQUE), expiresAt.

Estados de invitacion

EstadoDescripcion
PENDINGInvitacion enviada, esperando respuesta
ACCEPTEDColaborador tiene acceso al evento
DECLINEDColaborador rechazo
EXPIREDToken expiro
CANCELLEDOrganizador cancelo la invitacion

Roles asignables

RolAcceso
ORGANIZATION_ADMINAdministracion completa del evento
EVENT_COORDINATORCoordinacion operativa sin acceso financiero
EVENT_VIEWERSolo lectura
EVENT_STAFFCheck-in y operaciones del dia del evento

Flujo

  1. El organizador invita a un colaborador proporcionando su email y el rol deseado.
  2. El sistema genera un token unico con fecha de expiracion y envia la invitacion por correo.
  3. El colaborador abre el enlace con el token.
  4. Si el colaborador ya tiene cuenta en Nvito, se le asigna el rol en el evento automaticamente.
  5. Si no tiene cuenta, se le invita a registrarse y al completar el registro se le asigna el rol.
  6. El organizador puede cancelar invitaciones pendientes en cualquier momento.

Referencias

Archivos fuente

ArchivoDescripcion
events.controller.tsControlador de eventos: CRUD y cancelacion
event-lifecycle.service.tsMaquina de estados y transiciones automaticas
guests.controller.tsCRUD de invitados con importacion CSV
rsvp.controller.tsEndpoints de RSVP (publico y autenticado)
event-service.types.tsEnum TypeScript de los 18 servicios
schema.prismaModelos de datos de todo el sistema

Guards de autorizacion

  1. ClerkAuthGuard - Autenticacion JWT via Clerk.
  2. PermissionsGuard - Verificacion de permisos RBAC con @RequirePermission().
  3. EventAccessGuard - Acceso al evento especifico con @RequireEventAccess().
  4. InvitationStateGuard - Bloquea edicion si la invitacion esta publicada o cerrada.
Esta pagina fue util?