Módulo Starred Messages
src/app/modules/starred-message/
Permite que cada agente marque mensajes como destacados (con estrella), tanto de conversaciones con contactos como de chats internos (ver Internal Chat). Los destacados son personales: cada agente solo ve los suyos.
Modelo — StarredMessage
Colección starred_messages, con timestamps.
| Campo | Tipo | Descripción |
|---|---|---|
identifier | string (UUID) | ID externo único |
tenantId | ObjectId → Tenant | Tenant |
agentId | ObjectId → User | Agente que destacó el mensaje |
messageType | enum | contact o internal |
messageRefModel | enum | Message o InternalMessage; se deriva de messageType y alimenta el refPath |
messageId | ObjectId | Mensaje destacado (referencia polimórfica según messageRefModel) |
contactId | ObjectId → Contact | Opcional; solo para messageType = contact (se desnormaliza desde el ticket del mensaje) |
conversationId | ObjectId → Conversation | Opcional; solo para messageType = internal |
Índices:
- Único
(agentId, messageId, messageType): un agente no puede destacar dos veces el mismo mensaje. (agentId, contactId, createdAt desc),(agentId, conversationId, createdAt desc)y(agentId, createdAt desc)para los listados por alcance.
Endpoints
Base: /api/v1/starred-messages. El controlador usa solo @Auth(): no hay @RequirePermission; cualquier usuario autenticado puede usar el módulo y siempre opera sobre sus propios destacados (agentId y tenantId salen del usuario autenticado).
| Método | Ruta | Descripción |
|---|---|---|
POST | /starred-messages/toggle/:messageId | Destaca o quita el destacado; devuelve data { starred } |
GET | /starred-messages/by-contact/:contactId | Destacados de un contacto, paginado |
GET | /starred-messages/by-internal-conversation/:conversationId | Destacados de una conversación interna, paginado |
GET | /starred-messages/ids | Solo los ids de los mensajes destacados (filtrables por alcance); devuelve data { ids } |
GET | /starred-messages | Listado global del agente, paginado y filtrable por messageType |
Los listados paginados devuelven data con results y meta { total, page, limit, totalPages }. Cada resultado incluye el mensaje original y datos hidratados del remitente y del archivo adjunto, calculados solo para la página actual.
DTOs
Validaciones de class-validator.
Parámetros de ruta
| Parámetro | Tipo | Obligatorio | Validación | Usado en |
|---|---|---|---|---|
messageId | string | Sí | Ninguna en el controlador; se convierte con new Types.ObjectId | toggle/:messageId |
contactId | string | Sí | Ninguna; se convierte con new Types.ObjectId | by-contact/:contactId |
conversationId | string | Sí | Ninguna; se convierte con new Types.ObjectId | by-internal-conversation/:conversationId |
ToggleStarredMessageDto (body de POST /starred-messages/toggle/:messageId)
| Campo | Tipo | Obligatorio | Validaciones | Descripción |
|---|---|---|---|---|
messageType | string | Sí | @IsEnum: contact, internal | Indica si el mensaje es de un contacto o interno |
QueryStarredMessagesDto (query de los cuatro GET)
Todos los campos son opcionales, pero cada endpoint usa solo parte de ellos.
| Campo | Tipo | Obligatorio | Validaciones | Descripción | Usado en |
|---|---|---|---|---|---|
page | number | No | @Transform(toInt), @IsInt, @Min(1) | Página (por defecto 1) | Listados paginados |
limit | number | No | @Transform(toInt), @IsInt, @Min(1), @Max(100) | Tamaño de página (por defecto 10) | Listados paginados |
messageType | string | No | @IsEnum: contact, internal | Filtra el listado global por tipo | GET /starred-messages |
contactId | string | No | @IsMongoId | Restringe los ids a un contacto | GET /ids |
conversationId | string | No | @IsMongoId | Restringe los ids a una conversación interna | GET /ids |
Servicio
StarredMessageService.toggle busca el mensaje dentro del tenant (en Message o InternalMessage según messageType; si no existe responde 404). Para mensajes de contacto resuelve el contactId desde el ticket del mensaje; para internos toma el conversationId del mensaje. Después, el repositorio alterna el registro: si existe lo borra (starred: false) y si no lo crea (starred: true).
Gotchas
- Un id mal formado en los parámetros de ruta provoca un error de conversión de ObjectId sin validación previa (no hay
ParseObjectIdPipe). - En
by-contactyby-internal-conversationsolo se usanpageylimitdel query; los demás campos se ignoran. - Aunque el catálogo RBAC incluye el módulo
STARRED_MESSAGE(ver RBAC), este controlador no exige esos permisos. - La respuesta de
GET /idstraduce el mensaje sin pasar el idioma de la petición.