# Sistema de Notificaciones

**Versión:** 1.0.0
**Origen:** projects/gamilit
**Estado:** Producción
**Última actualización:** 2025-12-08

---

## Descripción

Sistema completo de notificaciones multi-canal:
- Notificaciones in-app (popups, bell icon)
- Notificaciones por email (SMTP, SendGrid)
- Push notifications (Web Push API nativo)
- Templates con interpolación de variables
- Preferencias por usuario y tipo
- Cola asíncrona para procesamiento

---

## Características

| Característica | Descripción |
|----------------|-------------|
| Multi-canal | in_app, email, push |
| Templates | Sistema de templates con variables |
| Preferencias | Por usuario y tipo de notificación |
| Cola Asíncrona | Procesamiento en background |
| Prioridades | low, normal, high, urgent |
| Expiración | Notificaciones con fecha de vencimiento |
| Logs | Registro de entregas y fallos |

---

## Stack Tecnológico

```yaml
backend:
  framework: NestJS
  orm: TypeORM
  email: Nodemailer + SendGrid
  push: web-push (Web Push API nativo VAPID)

database:
  engine: PostgreSQL
  schema: notifications
```

---

## Dependencias NPM

```json
{
  "nodemailer": "^6.x",
  "@nestjs-modules/mailer": "^1.x",
  "web-push": "^3.x",
  "typeorm": "^0.3.x"
}
```

---

## Tablas Requeridas

| Tabla | Propósito |
|-------|-----------|
| notifications.notifications | Notificaciones principales |
| notifications.notification_preferences | Preferencias por usuario/tipo |
| notifications.notification_templates | Templates con variables |
| notifications.notification_queue | Cola de procesamiento |
| notifications.notification_logs | Historial de entregas |
| notifications.user_devices | Dispositivos para push |

---

## Estructura del Módulo

```
notifications/
├── notifications.module.ts
├── controllers/
│   ├── notifications.controller.ts       # CRUD notificaciones
│   ├── notification-preferences.controller.ts
│   ├── notification-templates.controller.ts
│   └── notification-devices.controller.ts
├── services/
│   ├── notification.service.ts           # Servicio principal
│   ├── notification-preference.service.ts
│   ├── notification-template.service.ts
│   ├── notification-queue.service.ts     # Cola asíncrona
│   ├── push-notification.service.ts      # Web Push
│   └── user-device.service.ts
├── entities/
│   ├── notification.entity.ts
│   ├── notification-preference.entity.ts
│   ├── notification-template.entity.ts
│   ├── notification-queue.entity.ts
│   ├── notification-log.entity.ts
│   └── user-device.entity.ts
└── dto/
    ├── create-notification.dto.ts
    ├── notification-response.dto.ts
    └── ...

mail/
├── mail.module.ts
├── mail.service.ts                       # Envío de emails
└── templates/
    └── notification.templates.ts         # Templates HTML
```

---

## Canales de Notificación

### 1. In-App

```typescript
// Se muestra en bell icon y como popup
{
  channels: ['in_app'],
  // El frontend consulta notificaciones no leídas
  // WebSocket puede notificar en tiempo real
}
```

### 2. Email

```typescript
// Envío vía SMTP o SendGrid
{
  channels: ['email'],
  // Se usa template HTML
  // Retry con backoff exponencial
}
```

### 3. Push

```typescript
// Web Push API nativo (VAPID)
{
  channels: ['push'],
  // No requiere Firebase/OneSignal
  // Compatible con Chrome, Firefox, Safari 16.4+
}
```

---

## Uso Rápido

### 1. Crear notificación ad-hoc

```typescript
import { NotificationService } from '@/modules/notifications/services';

await notificationService.create({
  userId: 'user-uuid',
  title: 'Nuevo logro desbloqueado!',
  message: 'Has completado 10 ejercicios',
  type: 'achievement',
  channels: ['in_app', 'email'],
  priority: 'normal',
  data: {
    achievement_id: 'ach-001',
    xp_reward: 100,
  },
});
```

### 2. Usar template

```typescript
await notificationService.sendFromTemplate({
  templateKey: 'achievement_unlocked',
  userId: 'user-uuid',
  variables: {
    achievement_name: 'Primer Ejercicio',
    xp_earned: '100',
  },
  channels: ['in_app', 'push'],
});
```

### 3. Obtener notificaciones del usuario

```typescript
const { data, total } = await notificationService.findAllByUser(userId, {
  status: 'sent',        // pending, sent, read, failed
  type: 'achievement',   // filtrar por tipo
  limit: 20,
  offset: 0,
});
```

### 4. Marcar como leída

```typescript
await notificationService.markAsRead(notificationId, userId);
// o todas
await notificationService.markAllAsRead(userId);
```

### 5. Contador de no leídas

```typescript
const unreadCount = await notificationService.getUnreadCount(userId);
```

---

## Sistema de Preferencias

Los usuarios pueden configurar qué canales usar para cada tipo de notificación:

```typescript
// Estructura de preferencia
{
  userId: 'user-uuid',
  notificationType: 'achievement',  // tipo de notificación
  inAppEnabled: true,               // mostrar en app
  emailEnabled: false,              // no enviar email
  pushEnabled: true,                // enviar push
}
```

### Tipos de notificación comunes

| Tipo | Descripción | Canales por defecto |
|------|-------------|---------------------|
| achievement | Logros desbloqueados | in_app, push |
| rank_up | Subida de rango | in_app, email, push |
| assignment_due | Recordatorio de tarea | in_app, email |
| friend_request | Solicitud de amistad | in_app, push |
| system | Anuncios del sistema | in_app, email |
| password_reset | Reset de contraseña | email |

---

## Servicio de Email

### Configuración SMTP

```env
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=user@example.com
SMTP_PASS=password
SMTP_SECURE=false
SMTP_FROM="App Name <noreply@example.com>"
```

### Configuración SendGrid

```env
SENDGRID_API_KEY=SG.xxxxxx
```

### Métodos disponibles

```typescript
class MailService {
  // Email genérico
  async sendEmail(to, subject, html, text?): Promise<boolean>;

  // Email de notificación con template
  async sendNotificationEmail(to, title, message, actionUrl?, actionText?): Promise<boolean>;

  // Emails específicos
  async sendPasswordResetEmail(email, token, userName?): Promise<void>;
  async sendVerificationEmail(email, token, userName?): Promise<void>;
  async sendWelcomeEmail(email, userName, role): Promise<void>;
}
```

---

## Push Notifications (Web Push)

### Configuración VAPID

```env
VAPID_PUBLIC_KEY=BN...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:admin@example.com
```

Generar claves:
```bash
npx web-push generate-vapid-keys
```

### Flujo de registro

```typescript
// 1. Frontend obtiene subscription del navegador
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: VAPID_PUBLIC_KEY,
});

// 2. Enviar subscription al backend
await fetch('/api/notifications/devices', {
  method: 'POST',
  body: JSON.stringify({
    subscription,
    deviceType: 'web',
    browser: 'Chrome',
  }),
});
```

---

## Variables de Entorno

```env
# Email - SMTP
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=user
SMTP_PASS=pass
SMTP_SECURE=false
SMTP_FROM="App <noreply@app.com>"

# Email - SendGrid (alternativo)
SENDGRID_API_KEY=SG.xxx

# Push Notifications
VAPID_PUBLIC_KEY=BN...
VAPID_PRIVATE_KEY=...
VAPID_SUBJECT=mailto:admin@app.com

# Frontend URL (para links en emails)
FRONTEND_URL=https://app.example.com
```

---

## Endpoints Principales

| Método | Ruta | Descripción |
|--------|------|-------------|
| GET | /notifications | Listar notificaciones del usuario |
| GET | /notifications/unread-count | Contador de no leídas |
| POST | /notifications/:id/read | Marcar como leída |
| POST | /notifications/read-all | Marcar todas como leídas |
| DELETE | /notifications/:id | Eliminar notificación |
| GET | /notifications/preferences | Obtener preferencias |
| PUT | /notifications/preferences | Actualizar preferencias |
| POST | /notifications/devices | Registrar dispositivo push |
| DELETE | /notifications/devices/:id | Eliminar dispositivo |

---

## Flujo de Envío

```
1. Crear notificación (service o trigger SQL)
        │
        ▼
2. Verificar preferencias del usuario
        │
        ├─► in_app habilitado? → Guardar en BD
        │
        ├─► email habilitado? → Encolar en notification_queue
        │
        └─► push habilitado? → Encolar en notification_queue
        │
        ▼
3. Worker procesa cola (cron job)
        │
        ├─► Enviar email via MailService
        │
        └─► Enviar push via PushNotificationService
        │
        ▼
4. Registrar resultado en notification_logs
```

---

## Adaptaciones Necesarias

1. **Tipos de notificación**: Definir tipos específicos del proyecto
2. **Templates**: Crear templates HTML para emails
3. **Canales**: Ajustar canales por defecto según necesidades
4. **VAPID keys**: Generar claves únicas para push
5. **Proveedor email**: Configurar SMTP o SendGrid

---

## Referencias

- [Web Push Protocol](https://developers.google.com/web/fundamentals/push-notifications)
- [Nodemailer](https://nodemailer.com/)
- [SendGrid Docs](https://docs.sendgrid.com/)

---

**Mantenido por:** Sistema NEXUS
**Proyecto origen:** Gamilit Platform
