- Create TASK-2026-01-25-NOTIFICACIONES-COMPLETAS with full CAPVED docs - Update DATABASE_INVENTORY with auth.notifications, auth.user_push_tokens, investment.distribution_history, investment.distribution_runs tables - Update BACKEND_INVENTORY with push-token endpoints, firebase.client, and unit tests - Update FRONTEND_INVENTORY with notification components, store, service - Update MASTER_INVENTORY with updated totals - Update _INDEX.yml with new task entry Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
160 lines
4.1 KiB
Markdown
160 lines
4.1 KiB
Markdown
# 05-EJECUCION - Phase 1 MVP Implementation
|
|
|
|
## Resumen de Ejecución
|
|
|
|
**Fecha**: 2026-01-25
|
|
**Agente**: claude-opus-4.5
|
|
**Duración**: ~30 minutos
|
|
|
|
## Archivos Creados
|
|
|
|
### 1. Módulo de Notificaciones
|
|
|
|
#### notification.service.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/notifications/services/notification.service.ts
|
|
Líneas: ~650
|
|
|
|
Funcionalidades:
|
|
- sendNotification(userId, payload, options)
|
|
- sendBulkNotification(userIds, payload, options)
|
|
- broadcastNotification(payload)
|
|
- sendInAppNotification(userId, notification) - via WebSocket
|
|
- sendEmailNotification(userId, payload) - via nodemailer
|
|
- sendPushNotification(userId, payload) - estructura para FCM/APNS
|
|
- getUserNotifications(userId, options)
|
|
- markAsRead(notificationId, userId)
|
|
- markAllAsRead(userId)
|
|
- getUnreadCount(userId)
|
|
- deleteNotification(notificationId, userId)
|
|
- getUserPreferences(userId)
|
|
- updateUserPreferences(userId, updates)
|
|
- sendAlertNotification(userId, alert) - para price alerts
|
|
- sendTradeNotification(userId, trade)
|
|
- sendDistributionNotification(userId, distribution)
|
|
|
|
Templates de Email:
|
|
- alert_triggered
|
|
- trade_executed
|
|
- deposit_confirmed
|
|
- withdrawal_completed
|
|
- distribution_received
|
|
- system_announcement
|
|
- security_alert
|
|
- account_update
|
|
```
|
|
|
|
#### notification.controller.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/notifications/controllers/notification.controller.ts
|
|
Líneas: ~180
|
|
|
|
Endpoints:
|
|
- getNotifications: GET /notifications
|
|
- getUnreadCount: GET /notifications/unread-count
|
|
- markAsRead: PATCH /notifications/:id/read
|
|
- markAllAsRead: POST /notifications/read-all
|
|
- deleteNotification: DELETE /notifications/:id
|
|
- getPreferences: GET /notifications/preferences
|
|
- updatePreferences: PATCH /notifications/preferences
|
|
```
|
|
|
|
#### notification.routes.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/notifications/notification.routes.ts
|
|
Líneas: ~50
|
|
|
|
Rutas protegidas con requireAuth
|
|
```
|
|
|
|
#### notifications/index.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/notifications/index.ts
|
|
Líneas: ~10
|
|
|
|
Exports: notificationService, notificationRouter
|
|
```
|
|
|
|
### 2. Job de Distribución
|
|
|
|
#### distribution.job.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/investment/jobs/distribution.job.ts
|
|
Líneas: ~350
|
|
|
|
Funcionalidades:
|
|
- start(): Programa ejecución diaria a 00:00 UTC
|
|
- stop(): Detiene el scheduler
|
|
- run(): Ejecuta distribución manual o programada
|
|
- getActiveAccounts(): Obtiene cuentas activas con balance > 0
|
|
- getProducts(): Obtiene productos con tasas de retorno
|
|
- distributeReturns(account, product): Calcula y distribuye rendimientos
|
|
- notifyUser(result): Envía notificación de distribución
|
|
- logDistributionRun(summary): Registra auditoría
|
|
- getStatus(): Estado del job
|
|
- triggerManually(): Para admin/testing
|
|
|
|
Lógica de Distribución:
|
|
- Daily rate = (targetReturnMin + targetReturnMax) / 2 / 30
|
|
- Varianza aleatoria: -15% a +35%
|
|
- Performance fee aplicado sobre rendimiento bruto
|
|
- Solo distribuye si rendimiento neto > 0
|
|
- Transacción atómica con lock de fila
|
|
```
|
|
|
|
#### investment/jobs/index.ts
|
|
```
|
|
Ubicación: apps/backend/src/modules/investment/jobs/index.ts
|
|
Líneas: ~5
|
|
|
|
Export: distributionJob
|
|
```
|
|
|
|
## Archivos Modificados
|
|
|
|
### alerts.service.ts
|
|
```
|
|
Cambios:
|
|
+1 import: notificationService
|
|
+15 líneas en triggerAlert(): Llamada a sendAlertNotification
|
|
|
|
Antes:
|
|
// TODO: Send notifications based on notify_email and notify_push
|
|
|
|
Después:
|
|
try {
|
|
await notificationService.sendAlertNotification(alert.userId, {
|
|
symbol: alert.symbol,
|
|
condition: alert.condition,
|
|
targetPrice: alert.price,
|
|
currentPrice,
|
|
note: alert.note,
|
|
});
|
|
} catch (error) {
|
|
logger.error('[AlertsService] Failed to send alert notification:', {...});
|
|
}
|
|
```
|
|
|
|
### index.ts (main)
|
|
```
|
|
Cambios:
|
|
+1 import: distributionJob
|
|
+1 import: notificationRouter
|
|
+1 línea: apiRouter.use('/notifications', notificationRouter)
|
|
+1 línea: distributionJob.start() (después de WebSocket init)
|
|
+1 línea: distributionJob.stop() (en graceful shutdown)
|
|
```
|
|
|
|
## Validación Final
|
|
|
|
```bash
|
|
# TypeScript check para archivos de notificaciones
|
|
npx tsc --noEmit 2>&1 | grep -E "(notification|distribution)"
|
|
# Sin errores
|
|
```
|
|
|
|
## Estado Final
|
|
|
|
✅ Task 10: Notification Service - COMPLETADA
|
|
✅ Task 11: Distribution Job - COMPLETADA
|