# RF-NOTIF-004: Preferencias de Notificacion

## Identificacion

| Campo | Valor |
|-------|-------|
| **ID** | RF-NOTIF-004 |
| **Modulo** | MGN-008 Notifications |
| **Titulo** | Preferencias de Notificacion |
| **Prioridad** | P1 - Alta |
| **Estado** | Draft |
| **Fecha** | 2025-12-05 |

---

## Descripcion

El sistema debe permitir a cada usuario configurar sus preferencias de notificacion, incluyendo canales habilitados, tipos de notificaciones, horarios de silencio, y frecuencia de resumenes.

---

## Requisitos Funcionales

### RF-NOTIF-004.1: Estructura de Preferencias

```typescript
interface NotificationPreferences {
  userId: UUID;

  // Canales globales
  channels: {
    inApp: boolean;
    email: boolean;
    push: boolean;
    sms?: boolean;  // Futuro
  };

  // Por tipo de notificacion
  byType: {
    [notificationType: string]: {
      enabled: boolean;
      channels: ('inApp' | 'email' | 'push')[];
    };
  };

  // Horarios
  quietHours: {
    enabled: boolean;
    timezone: string;
    start: string;  // "22:00"
    end: string;    // "08:00"
    days: number[]; // [0,1,2,3,4,5,6] (dom-sab)
  };

  // Resumenes
  digest: {
    enabled: boolean;
    frequency: 'none' | 'daily' | 'weekly';
    time: string;   // "09:00"
    dayOfWeek?: number;  // Para weekly (1=Lunes)
  };

  // Miscelaneo
  soundEnabled: boolean;
  desktopEnabled: boolean;
  language: string;
}
```

### RF-NOTIF-004.2: Canales por Tipo de Notificacion

Matriz de configuracion:

| Tipo | In-App | Email | Push | Default |
|------|--------|-------|------|---------|
| task_assigned | Si | Si | Si | In-App, Push |
| task_due | Si | Si | Si | In-App, Email, Push |
| approval_requested | Si | Si | Si | Todos |
| order_created | Si | Si | No | In-App, Email |
| payment_received | Si | Si | No | In-App, Email |
| system_alert | Si | Si | Si | Todos (no configurable) |
| marketing | No | Si | No | Email (opt-in) |

### RF-NOTIF-004.3: Valores por Defecto

Cada tenant puede definir defaults:

```typescript
interface TenantNotificationDefaults {
  tenantId: UUID;
  defaults: NotificationPreferences;
  overridableByUser: boolean;  // Puede el usuario cambiarlos?
  mandatoryTypes: string[];    // Tipos no deshabilitables
}
```

### RF-NOTIF-004.4: Digest (Resumen)

Emails de resumen agrupados:

```typescript
interface DigestEmail {
  frequency: 'daily' | 'weekly';
  sections: {
    title: string;
    notifications: {
      type: string;
      count: number;
      summary: string;
      link: string;
    }[];
  }[];
  unreadTotal: number;
  period: { from: Date; to: Date };
}

// Ejemplo de digest diario
{
  "sections": [
    {
      "title": "Tareas",
      "notifications": [
        { "type": "task_assigned", "count": 3, "summary": "3 nuevas tareas" },
        { "type": "task_due", "count": 2, "summary": "2 tareas vencen hoy" }
      ]
    },
    {
      "title": "Pedidos",
      "notifications": [
        { "type": "order_created", "count": 5, "summary": "5 nuevos pedidos" }
      ]
    }
  ],
  "unreadTotal": 10
}
```

### RF-NOTIF-004.5: Unsubscribe Link

Cada email incluye:

```
Para dejar de recibir estos emails, haz click aqui:
https://app.example.com/unsubscribe?token=xxx&type=order_created
```

- Token firmado con expiracion
- Permite desuscribir tipo especifico o todos los emails
- No requiere login

---

## Operaciones

### Obtener Preferencias

```typescript
GET /api/v1/notifications/preferences

Response:
{
  "channels": {
    "inApp": true,
    "email": true,
    "push": true
  },
  "byType": {
    "task_assigned": {
      "enabled": true,
      "channels": ["inApp", "push"]
    },
    "marketing": {
      "enabled": false,
      "channels": []
    }
  },
  "quietHours": {
    "enabled": true,
    "start": "22:00",
    "end": "08:00"
  },
  "digest": {
    "enabled": true,
    "frequency": "daily",
    "time": "09:00"
  }
}
```

### Actualizar Preferencias

```typescript
PATCH /api/v1/notifications/preferences
{
  "channels": {
    "push": false
  },
  "byType": {
    "task_assigned": {
      "channels": ["inApp", "email"]
    }
  }
}
```

### Deshabilitar Tipo (Unsubscribe)

```typescript
POST /api/v1/notifications/unsubscribe
{
  "token": "signed-token",
  "type": "order_created"  // o "all" para todos los emails
}

// Sin autenticacion, validado por token
```

### Obtener Tipos Disponibles

```typescript
GET /api/v1/notifications/types

Response:
{
  "types": [
    {
      "type": "task_assigned",
      "name": "Tarea asignada",
      "description": "Cuando te asignan una nueva tarea",
      "category": "tasks",
      "availableChannels": ["inApp", "email", "push"],
      "defaultChannels": ["inApp", "push"],
      "canDisable": true
    },
    {
      "type": "system_alert",
      "name": "Alertas del sistema",
      "description": "Alertas criticas del sistema",
      "category": "system",
      "availableChannels": ["inApp", "email", "push"],
      "defaultChannels": ["inApp", "email", "push"],
      "canDisable": false
    }
  ]
}
```

---

## Reglas de Negocio

| ID | Regla | Severidad |
|----|-------|-----------|
| BR-001 | Alertas de sistema no deshabilitables | Security |
| BR-002 | Quiet hours no afectan alertas criticas | Security |
| BR-003 | Unsubscribe token expira en 7 dias | Security |
| BR-004 | Nuevos usuarios usan defaults del tenant | UX |
| BR-005 | Digest solo si hay notificaciones | UX |

---

## Criterios de Aceptacion

- [ ] Configuracion por canal (in-app, email, push)
- [ ] Configuracion por tipo de notificacion
- [ ] Quiet hours con timezone
- [ ] Digest diario/semanal
- [ ] Unsubscribe sin login
- [ ] Defaults por tenant
- [ ] UI de preferencias intuitiva

---

## Historial

| Version | Fecha | Autor | Cambios |
|---------|-------|-------|---------|
| 1.0 | 2025-12-05 | Requirements-Analyst | Creacion inicial |
