# US-INV-012: Recibir Notificaciones ## Metadata | Campo | Valor | |-------|-------| | **ID** | US-INV-012 | | **Épica** | OQI-004 - Cuentas de Inversión | | **Módulo** | investment | | **Prioridad** | P2 | | **Story Points** | 3 | | **Sprint** | Sprint 7 | | **Estado** | Pendiente | | **Asignado a** | Por asignar | --- ## Historia de Usuario **Como** inversor, **quiero** recibir notificaciones sobre eventos importantes de mi cuenta, **para** estar informado en tiempo real sobre depósitos, retiros, distribuciones y actividad del agente. ## Descripción Detallada El usuario debe poder configurar y recibir notificaciones por diferentes canales (email, push, in-app) sobre eventos clave: depósito completado, retiro procesado, distribución mensual, grandes ganancias/pérdidas, alertas de rendimiento, y más. Debe poder personalizar qué notificaciones recibir y por qué canal. ## Mockups/Wireframes ``` ┌─────────────────────────────────────────────────────────────────┐ │ CONFIGURACIÓN DE NOTIFICACIONES │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Elige cómo quieres recibir notificaciones: │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Tipo de Notificación │ Email │ Push │ In-App │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 💰 Depósito completado │ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 💸 Retiro procesado │ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 📊 Distribución mensual │ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 🎉 Ganancia grande (>5%) │ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ ⚠️ Pérdida importante (>3%)│ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 📈 Nuevo récord de balance │ [x] │ [ ] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 🤖 Agente abrió posición │ [ ] │ [ ] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 🤖 Agente cerró posición │ [ ] │ [ ] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 📉 Drawdown alcanzó límite │ [x] │ [x] │ [x] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 📬 Resumen semanal │ [x] │ [ ] │ [ ] │ │ │ ├──────────────────────────────────────────────────────────┤ │ │ │ 🔔 Actualizaciones sistema │ [x] │ [ ] │ [x] │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Horario de notificaciones push │ │ │ │ [x] Respetar horario (solo 9am - 9pm) │ │ │ │ [ ] Recibir en cualquier horario │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ [Guardar Preferencias] │ │ │ │ ───────────────────────────────────────────────────────────── │ │ │ │ NOTIFICACIONES RECIENTES │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 🎉 Ganancia importante Hace 2h │ │ │ │ Tu agente Atlas generó +$125 en un trade (+5.2%) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 💰 Depósito completado Ayer │ │ │ │ Tu depósito de $1,000 fue procesado exitosamente │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ 📊 Distribución mensual Hace 5 días │ │ │ │ Ganaste $48 este mes (+4.8%) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ │ [Ver todas las notificaciones →] │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## Criterios de Aceptación **Escenario 1: Configurar preferencias de notificaciones** ```gherkin DADO que el usuario está en configuración de notificaciones CUANDO marca "Email" para "Depósito completado" Y desmarca "Push" para "Agente abrió posición" Y hace click en "Guardar Preferencias" ENTONCES se guardan las preferencias Y se muestra confirmación "Preferencias guardadas" Y las notificaciones futuras respetan la configuración ``` **Escenario 2: Recibir notificación de depósito** ```gherkin DADO que el usuario tiene notificaciones de depósito activadas (email + push) CUANDO se completa un depósito de $1,000 ENTONCES se envía email con asunto "Depósito completado - $1,000" Y se envía notificación push Y se crea notificación in-app Y el contador de notificaciones se incrementa ``` **Escenario 3: Notificación de ganancia grande** ```gherkin DADO que el agente cierra trade con ganancia de $125 (+5.2%) Y supera el umbral de 5% CUANDO se procesa el trade ENTONCES se envía notificación "Ganancia importante" Y incluye monto y porcentaje Y link para ver detalle del trade ``` **Escenario 4: Ver notificaciones in-app** ```gherkin DADO que el usuario tiene 5 notificaciones sin leer CUANDO hace click en el icono de notificaciones ENTONCES se abre panel lateral con lista Y muestra las 5 notificaciones ordenadas por fecha Y las más recientes están resaltadas Y al hacer click en una, se marca como leída ``` **Escenario 5: Respetar horario de push** ```gherkin DADO que el usuario tiene "Respetar horario" activado Y son las 11pm (fuera de horario) CUANDO ocurre un evento que genera notificación push ENTONCES NO se envía push en ese momento Y se envía al día siguiente a las 9am Y las notificaciones in-app siguen funcionando normalmente ``` **Escenario 6: Resumen semanal por email** ```gherkin DADO que es lunes a las 9am Y el usuario tiene "Resumen semanal" activado CUANDO se ejecuta el cron job de resúmenes ENTONCES se envía email con resumen de la semana pasada Y incluye: balance inicial/final, trades, rendimiento, top ganancias ``` **Escenario 7: Desactivar todas las notificaciones** ```gherkin DADO que el usuario quiere pausar todas las notificaciones CUANDO desmarca todos los checkboxes Y guarda ENTONCES NO se envían notificaciones de ningún tipo Y se muestra advertencia "No recibirás notificaciones" ``` ## Criterios Adicionales - [ ] Badge de contador en icono de notificaciones - [ ] Marcar todas como leídas con un click - [ ] Eliminar notificaciones antiguas (>30 días) - [ ] Notificaciones agrupadas ("3 trades cerrados hoy") - [ ] Deep links desde notificaciones a secciones específicas --- ## Tareas Técnicas **Database:** - [ ] DB-INV-001: Tabla notifications.preferences (por usuario) - [ ] DB-INV-002: Tabla notifications.notifications - [ ] DB-INV-003: Índices en (user_id, read, created_at) **Backend:** - [ ] BE-INV-001: Endpoint GET /notifications/preferences - [ ] BE-INV-002: Endpoint PUT /notifications/preferences - [ ] BE-INV-003: Implementar NotificationService.send() - [ ] BE-INV-004: Email notifications (Nodemailer/SendGrid) - [ ] BE-INV-005: Push notifications (Firebase Cloud Messaging) - [ ] BE-INV-006: Endpoint GET /notifications (lista) - [ ] BE-INV-007: Endpoint PATCH /notifications/:id/read - [ ] BE-INV-008: Endpoint PATCH /notifications/mark-all-read - [ ] BE-INV-009: Cron job para resumen semanal - [ ] BE-INV-010: Event emitter para disparar notificaciones - [ ] BE-INV-011: Cleanup job para notificaciones antiguas **Frontend:** - [ ] FE-INV-001: Crear página NotificationsSettingsPage.tsx - [ ] FE-INV-002: Crear componente NotificationPreferences.tsx - [ ] FE-INV-003: Crear componente NotificationBell.tsx (header) - [ ] FE-INV-004: Crear componente NotificationsList.tsx - [ ] FE-INV-005: Crear componente NotificationItem.tsx - [ ] FE-INV-006: Integrar Firebase SDK para push - [ ] FE-INV-007: Solicitar permisos de notificaciones - [ ] FE-INV-008: Implementar notificationsStore - [ ] FE-INV-009: WebSocket para notificaciones en tiempo real **Tests:** - [ ] TEST-INV-001: Test guardado de preferencias - [ ] TEST-INV-002: Test envío de emails - [ ] TEST-INV-003: Test envío de push - [ ] TEST-INV-004: Test horario de notificaciones - [ ] TEST-INV-005: Test resumen semanal - [ ] TEST-INV-006: Test E2E flujo completo --- ## Dependencias **Depende de:** - [ ] Firebase Cloud Messaging configurado - [ ] Email service configurado (SendGrid/SES) **Bloquea:** - Ninguna --- ## Notas Técnicas **Endpoints involucrados:** | Método | Endpoint | Descripción | |--------|----------|-------------| | GET | /notifications/preferences | Obtener preferencias | | PUT | /notifications/preferences | Guardar preferencias | | GET | /notifications | Lista de notificaciones | | PATCH | /notifications/:id/read | Marcar como leída | | PATCH | /notifications/mark-all-read | Marcar todas | **Entidades/Tablas:** **notifications.preferences:** ```sql CREATE TABLE notifications.preferences ( user_id UUID PRIMARY KEY REFERENCES auth.users(id), deposit_completed_email BOOLEAN DEFAULT true, deposit_completed_push BOOLEAN DEFAULT true, deposit_completed_inapp BOOLEAN DEFAULT true, withdrawal_processed_email BOOLEAN DEFAULT true, withdrawal_processed_push BOOLEAN DEFAULT true, withdrawal_processed_inapp BOOLEAN DEFAULT true, monthly_distribution_email BOOLEAN DEFAULT true, monthly_distribution_push BOOLEAN DEFAULT true, monthly_distribution_inapp BOOLEAN DEFAULT true, large_profit_email BOOLEAN DEFAULT true, large_profit_push BOOLEAN DEFAULT true, large_profit_inapp BOOLEAN DEFAULT true, -- ... más tipos respect_quiet_hours BOOLEAN DEFAULT true, quiet_hours_start TIME DEFAULT '21:00', quiet_hours_end TIME DEFAULT '09:00', weekly_summary_email BOOLEAN DEFAULT true, updated_at TIMESTAMP DEFAULT NOW() ); ``` **notifications.notifications:** ```sql CREATE TABLE notifications.notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES auth.users(id), account_id UUID REFERENCES investment.accounts(id), type VARCHAR(50) NOT NULL, title VARCHAR(200) NOT NULL, message TEXT NOT NULL, data JSONB, read BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT NOW() ); ``` **Tipos de Notificación:** ```typescript enum NotificationType { DEPOSIT_COMPLETED = 'deposit_completed', WITHDRAWAL_PROCESSED = 'withdrawal_processed', MONTHLY_DISTRIBUTION = 'monthly_distribution', LARGE_PROFIT = 'large_profit', SIGNIFICANT_LOSS = 'significant_loss', NEW_BALANCE_RECORD = 'new_balance_record', POSITION_OPENED = 'position_opened', POSITION_CLOSED = 'position_closed', DRAWDOWN_LIMIT = 'drawdown_limit', WEEKLY_SUMMARY = 'weekly_summary', SYSTEM_UPDATE = 'system_update' } ``` **Response GET /notifications:** ```typescript { notifications: [ { id: "uuid", type: "large_profit", title: "Ganancia importante", message: "Tu agente Atlas generó +$125 en un trade (+5.2%)", data: { accountId: "uuid", tradeId: "uuid", amount: 125, percentage: 5.2 }, read: false, createdAt: "2025-12-05T08:30:00Z" } ], unreadCount: 3, pagination: { page: 1, total: 45 } } ``` **Lógica de Envío:** ```typescript class NotificationService { async send(userId: string, type: NotificationType, data: any) { const prefs = await this.getPreferences(userId); // In-app (siempre) if (prefs[`${type}_inapp`]) { await this.createInAppNotification(userId, type, data); } // Email if (prefs[`${type}_email`]) { await this.sendEmail(userId, type, data); } // Push if (prefs[`${type}_push`]) { if (this.isWithinQuietHours(prefs) && prefs.respect_quiet_hours) { await this.schedulePushForLater(userId, type, data); } else { await this.sendPush(userId, type, data); } } } } ``` **Email Templates:** - Usar HTML templates con branding - Incluir botones de acción (CTA) - Link de unsubscribe al final **Push Notifications:** - Firebase Cloud Messaging (FCM) - Solicitar permisos en frontend - Guardar FCM token en DB - Deeplinks a secciones específicas **Umbrales para Alertas:** - Ganancia grande: >5% en un trade - Pérdida importante: >3% en un trade - Drawdown límite: Alcanza 80% del max drawdown del producto --- ## Definition of Ready (DoR) - [x] Historia claramente escrita - [x] Criterios de aceptación definidos - [x] Story points estimados - [x] Dependencias identificadas - [ ] Firebase configurado - [ ] Email service configurado - [ ] Diseño/mockup disponible - [x] API spec disponible ## Definition of Done (DoD) - [ ] Código implementado según criterios - [ ] Tests unitarios escritos y pasando - [ ] Tests de integración pasando - [ ] Email templates creados - [ ] Push notifications funcionando - [ ] In-app notifications funcionando - [ ] Preferencias guardándose correctamente - [ ] Horario de quiet hours respetado - [ ] Code review aprobado - [ ] Documentación actualizada - [ ] QA aprobado - [ ] Desplegado en ambiente de pruebas --- ## Historial de Cambios | Fecha | Cambio | Autor | |-------|--------|-------| | 2025-12-05 | Creación | Requirements-Analyst | --- **Creada por:** Requirements-Analyst **Fecha:** 2025-12-05 **Última actualización:** 2025-12-05