- Add MetricsPage and useOnboarding hook - Update superadmin controller and service - Add module documentation (docs/01-modulos/) - Add CONTEXT-MAP.yml and Sprint 5 execution report - Update project status and task traces 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
212 lines
5.1 KiB
Markdown
212 lines
5.1 KiB
Markdown
# SAAS-007: Notificaciones
|
|
|
|
## Metadata
|
|
- **Codigo:** SAAS-007
|
|
- **Modulo:** Notifications
|
|
- **Prioridad:** P1
|
|
- **Estado:** Pendiente
|
|
- **Fase:** 3 - Features Core
|
|
|
|
## Descripcion
|
|
|
|
Sistema de notificaciones multicanal: email transaccional, push notifications (web/mobile), y notificaciones in-app con preferencias por usuario.
|
|
|
|
## Objetivos
|
|
|
|
1. Email transaccional con templates
|
|
2. Push notifications (web)
|
|
3. Notificaciones in-app
|
|
4. Preferencias por usuario
|
|
5. Historial de notificaciones
|
|
|
|
## Alcance
|
|
|
|
### Incluido
|
|
- Email via SendGrid/Resend
|
|
- Push web via Web Push API
|
|
- Notificaciones in-app en tiempo real
|
|
- Templates de email personalizables
|
|
- Preferencias de notificacion por usuario
|
|
- Queue de envio con reintentos
|
|
|
|
### Excluido
|
|
- SMS - fase posterior
|
|
- Push mobile nativo - fase posterior
|
|
- WhatsApp Business - fase posterior
|
|
|
|
## Canales Soportados
|
|
|
|
| Canal | Proveedor | Casos de Uso |
|
|
|-------|-----------|--------------|
|
|
| Email | SendGrid/Resend | Bienvenida, facturas, alertas |
|
|
| Push Web | Web Push API | Alertas tiempo real |
|
|
| In-App | WebSocket | Actualizaciones, menciones |
|
|
|
|
## Modelo de Datos
|
|
|
|
### Tablas (schema: notifications)
|
|
|
|
**notification_templates**
|
|
- id, code, name, description
|
|
- channel (email/push/inapp)
|
|
- subject_template, body_template
|
|
- variables (JSONB), is_active
|
|
|
|
**notifications**
|
|
- id, tenant_id, user_id
|
|
- template_code, channel
|
|
- subject, body, data (JSONB)
|
|
- status, sent_at, read_at
|
|
- created_at
|
|
|
|
**user_notification_preferences**
|
|
- id, user_id, channel
|
|
- enabled, categories (JSONB)
|
|
- quiet_hours_start, quiet_hours_end
|
|
|
|
**push_subscriptions**
|
|
- id, user_id, endpoint
|
|
- keys (JSONB), user_agent
|
|
- created_at, last_used_at
|
|
|
|
## Templates Predefinidos
|
|
|
|
| Codigo | Canal | Descripcion |
|
|
|--------|-------|-------------|
|
|
| welcome | email | Bienvenida nuevo usuario |
|
|
| invite | email | Invitacion a tenant |
|
|
| password_reset | email | Reset de password |
|
|
| invoice_paid | email | Factura pagada |
|
|
| trial_ending | email | Trial por terminar |
|
|
| new_comment | inapp | Nuevo comentario |
|
|
| mention | inapp/push | Mencion en comentario |
|
|
|
|
## Endpoints API
|
|
|
|
| Metodo | Endpoint | Descripcion |
|
|
|--------|----------|-------------|
|
|
| GET | /notifications | Listar notificaciones |
|
|
| GET | /notifications/unread | No leidas |
|
|
| PUT | /notifications/:id/read | Marcar leida |
|
|
| PUT | /notifications/read-all | Marcar todas leidas |
|
|
| DELETE | /notifications/:id | Eliminar |
|
|
| GET | /notifications/preferences | Preferencias |
|
|
| PUT | /notifications/preferences | Actualizar preferencias |
|
|
| POST | /notifications/push/subscribe | Suscribir push |
|
|
| DELETE | /notifications/push/unsubscribe | Desuscribir push |
|
|
|
|
## Interfaz del Servicio
|
|
|
|
```typescript
|
|
interface NotificationService {
|
|
send(userId: string, template: string, data: object): Promise<void>;
|
|
sendBulk(userIds: string[], template: string, data: object): Promise<void>;
|
|
sendToTenant(tenantId: string, template: string, data: object): Promise<void>;
|
|
}
|
|
|
|
interface NotificationPayload {
|
|
template: string;
|
|
channel?: 'email' | 'push' | 'inapp' | 'all';
|
|
data: Record<string, any>;
|
|
priority?: 'low' | 'normal' | 'high';
|
|
}
|
|
```
|
|
|
|
## Flujo de Envio
|
|
|
|
```
|
|
1. Evento dispara notificacion
|
|
2. NotificationService.send()
|
|
3. Cargar template y preferencias
|
|
4. Verificar canal habilitado
|
|
5. Renderizar template con datos
|
|
6. Encolar en BullMQ
|
|
7. Worker procesa y envia
|
|
8. Actualizar status
|
|
9. WebSocket notifica in-app
|
|
```
|
|
|
|
## Email Templates (MJML)
|
|
|
|
```typescript
|
|
// Template base
|
|
const baseTemplate = `
|
|
<mjml>
|
|
<mj-head>
|
|
<mj-attributes>
|
|
<mj-all font-family="Arial" />
|
|
</mj-attributes>
|
|
</mj-head>
|
|
<mj-body>
|
|
<mj-section>
|
|
<mj-column>
|
|
<mj-image src="{{tenant.logo}}" />
|
|
<mj-text>{{content}}</mj-text>
|
|
</mj-column>
|
|
</mj-section>
|
|
</mj-body>
|
|
</mjml>
|
|
`;
|
|
```
|
|
|
|
## Entregables
|
|
|
|
| Entregable | Estado | Archivo |
|
|
|------------|--------|---------|
|
|
| notifications.module.ts | Pendiente | `modules/notifications/` |
|
|
| email.service.ts | Pendiente | `services/` |
|
|
| push.service.ts | Pendiente | `services/` |
|
|
| notification.gateway.ts | Pendiente | `gateways/` |
|
|
| DDL notifications schema | Pendiente | `ddl/schemas/notifications/` |
|
|
| Seeds templates | Pendiente | `seeds/prod/notifications/` |
|
|
|
|
## Dependencias
|
|
|
|
### Depende de
|
|
- SAAS-001 (Auth)
|
|
- SAAS-002 (Tenants)
|
|
- SAAS-003 (Users)
|
|
- SendGrid/Resend API key
|
|
- VAPID keys para push
|
|
|
|
### Bloquea a
|
|
- Alertas en otros modulos
|
|
- Sistema de menciones
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
- [ ] Email de bienvenida se envia
|
|
- [ ] Push notifications funcionan
|
|
- [ ] In-app muestra en tiempo real
|
|
- [ ] Preferencias se respetan
|
|
- [ ] Quiet hours funcionan
|
|
- [ ] Templates son personalizables
|
|
|
|
## Configuracion
|
|
|
|
```typescript
|
|
{
|
|
notifications: {
|
|
email: {
|
|
provider: 'sendgrid', // o 'resend'
|
|
apiKey: process.env.SENDGRID_API_KEY,
|
|
from: 'noreply@example.com',
|
|
replyTo: 'support@example.com'
|
|
},
|
|
push: {
|
|
vapidPublicKey: process.env.VAPID_PUBLIC_KEY,
|
|
vapidPrivateKey: process.env.VAPID_PRIVATE_KEY,
|
|
subject: 'mailto:admin@example.com'
|
|
},
|
|
defaults: {
|
|
quietHoursStart: '22:00',
|
|
quietHoursEnd: '08:00'
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
**Ultima actualizacion:** 2026-01-07
|