# Resumen de ImplementaciΓ³n: API de Notificaciones - VoxPopuli **Fecha:** 29 de Abril de 2024 **VersiΓ³n:** 1.0.0 **Autor:** VoxPopuli Development Team --- ## πŸ“‹ Resumen Ejecutivo Se ha implementado **exitosamente** una nueva **API de Notificaciones** que se integra con la arquitectura existente del proyecto. Las notificaciones se disparan automΓ‘ticamente cuando los reportes cambian de estado, proporcionando a los usuarios actualizaciones en tiempo real sobre el progreso de sus reportes. ### Puntos Clave: βœ… Nueva API de Notificaciones en **puerto 8002** βœ… Base de datos MongoDB dedicada (`voxpopuli_notifications`) βœ… IntegraciΓ³n automΓ‘tica con eventos de cambio de estado de reportes βœ… Sistema de consumidores RabbitMQ para procesamiento asΓ­ncrono βœ… Arquitectura hexagonal consistente con el resto del proyecto βœ… Docker-compose actualizado con nuevos servicios --- ## πŸ“ Estructura de Archivos Creados ``` src/ β”œβ”€β”€ domain/ β”‚ └── notifications.py ✨ Nuevo β”œβ”€β”€ application/ β”‚ β”œβ”€β”€ ports/ β”‚ β”‚ └── notification_repository.py ✨ Nuevo β”‚ └── services/ β”‚ └── notification_services.py ✨ Nuevo β”œβ”€β”€ infrastructure/ β”‚ β”œβ”€β”€ adapters/ β”‚ β”‚ └── persistence/ β”‚ β”‚ └── notification_repository_mongo.py ✨ Nuevo β”‚ └── api/ β”‚ └── notifications/ ✨ Nuevo directorio β”‚ β”œβ”€β”€ __init__.py β”‚ β”œβ”€β”€ app.py β”‚ β”œβ”€β”€ router.py β”‚ β”œβ”€β”€ root.py β”‚ β”œβ”€β”€ schemas.py β”‚ └── notifications.py └── consumers/ └── notification_consumer.py ✨ Nuevo πŸ“„ FRONTEND_NOTIFICATIONS_IMPLEMENTATION.md ✨ Nuevo πŸ“„ IMPLEMENTATION_SUMMARY.md ✨ Nuevo (este archivo) ``` --- ## πŸ—οΈ Cambios en Archivos Existentes ### 1. `src/core/config.py` - ✏️ Agregado: `mongodb_notifications_db` para configuraciΓ³n de BD de notificaciones - ✏️ Actualizado comentario de `mongodb_url` para incluir ambas APIs ```python mongodb_notifications_db: str = Field( default="voxpopuli_notifications", description="Base de datos MongoDB para Notificaciones" ) ``` ### 2. `src/main.py` - ✏️ Importado: `create_notifications_app` desde API de notificaciones - ✏️ Importado: `NotificationConsumer` - ✏️ Agregado: Thread para ejecutar API de notificaciones (puerto 8002) - ✏️ Agregado: Thread para ejecutar consumidor de notificaciones - ✏️ Actualizado: Mensajes de inicio para mostrar la nueva API ```python # Cambios principales from infrastructure.api.notifications.app import create_app as create_notifications_app from consumers.notification_consumer import NotificationConsumer # Agregado en run(): notifications_thread = threading.Thread(target=run_notifications_api, daemon=True) notifications_consumer_thread = threading.Thread(target=run_notifications_consumer, daemon=True) ``` ### 3. `src/infrastructure/adapters/rabbitmq/messages.py` - ✏️ Agregado: Tipo de evento `UPDATE_STATUS` a `ReportEventType` - ✏️ Agregado: Campos `old_estado`, `new_estado`, `old_visibility`, `new_visibility` a `ReportMessage` ```python class ReportEventType(str, Enum): CREATE = "report.create" UPDATE_VISIBILITY = "report.update_visibility" UPDATE_STATUS = "report.update_status" # ✨ Nuevo DELETE = "report.delete" @dataclass class ReportMessage: # ... campos existentes ... old_estado: Optional[str] = None # ✨ Nuevo new_estado: Optional[str] = None # ✨ Nuevo ``` ### 4. `src/application/services/report_services.py` - ✏️ **Clase `UpdateReportStatus`:** Completamente refactorizada para enviar eventos a RabbitMQ - ✏️ Agregado: ImportaciΓ³n de `ReportMessage` y `send_to_queue` - ✏️ Agregado: LΓ³gica para crear mensaje UPDATE_STATUS y enviarlo a `notifications_queue` - ✏️ Agregado: Captura del estado anterior para comparaciΓ³n ```python # Cambios en UpdateReportStatus.execute(): old_estado = report.estado # Guardar estado anterior # DespuΓ©s de actualizar: if old_estado != new_estado: message = ReportMessage( event_type=ReportEventType.UPDATE_STATUS, id_reporte=report_id, id_usuario=report.id_usuario, old_estado=old_estado, new_estado=new_estado, # ... otros campos ... ) send_to_queue("notifications_queue", message.to_dict()) ``` ### 5. `docker-compose.yaml` - ✏️ **MongoDB:** Agregados credenciales de autenticaciΓ³n - Usuario: `admin` / ContraseΓ±a: `admin_password` - Agregado flag `--auth` en comando - ✏️ **Agregado:** Servicio RabbitMQ completo con: - Usuario: `voxpopuli` / ContraseΓ±a: `voxpopuli_pass` - Management UI en puerto 15672 - Healthcheck configurado - ✏️ **VolΓΊmenes:** Agregado `rabbitmq_data` para persistencia --- ## πŸš€ Nuevos Servicios en Docker Compose ### RabbitMQ (Nuevo) ```yaml rabbitmq: image: rabbitmq:3.13-management container_name: voxpopuli_rabbitmq ports: - "5672:5672" # AMQP - "15672:15672" # Management UI (http://localhost:15672) credentials: user: voxpopuli password: voxpopuli_pass ``` **Acceso Management UI:** - URL: http://localhost:15672 - Usuario: `voxpopuli` - ContraseΓ±a: `voxpopuli_pass` --- ## πŸ“Š Base de Datos MongoDB ### Nuevas Colecciones **Base de datos:** `voxpopuli_notifications` #### ColecciΓ³n: `notificaciones` ```json { "_id": ObjectId, "id_usuario": 1, "id_reporte": "uuid-del-reporte", "message": "Β‘Tu reporte #uuid ha sido resuelto!", "fecha": ISODate("2024-04-29T15:30:00Z"), "read": false } ``` **Índices Recomendados:** ```javascript db.notificaciones.createIndex({ "id_usuario": 1, "fecha": -1 }) db.notificaciones.createIndex({ "id_usuario": 1, "read": 1 }) ``` --- ## πŸ”„ Flujo de Eventos ### Cambio de Estado de Reporte β†’ NotificaciΓ³n ``` 1. Frontend llama: PUT /reports/{report_id}/status { "estado": "resuelto" } 2. API de Reportes: └─ UpdateReportStatus.execute() β”œβ”€ Valida estado β”œβ”€ Obtiene reporte actual (estado anterior) β”œβ”€ Actualiza en MongoDB └─ NUEVO: EnvΓ­a mensaje a RabbitMQ { "event_type": "report.update_status", "id_reporte": "uuid", "id_usuario": 1, "old_estado": "en proceso", "new_estado": "resuelto", ... } 3. RabbitMQ: └─ Almacena en queue `notifications_queue` 4. Consumidor de Notificaciones: β”œβ”€ Escucha la cola β”œβ”€ Recibe el evento UPDATE_STATUS └─ Procesa mensaje: └─ NotificationService.send_report_status_notification() └─ Crea notificaciΓ³n en MongoDB { "id_usuario": 1, "id_reporte": "uuid", "message": "Β‘Tu reporte ha sido resuelto!", "fecha": now(), "read": false } 5. Frontend (Polling o WebSocket): └─ GET /notifications/1 └─ Obtiene notificaciΓ³n creada ``` --- ## πŸ“‘ Colas RabbitMQ ### `reports_queue` - **PropΓ³sito:** Eventos de creaciΓ³n, eliminaciΓ³n y cambios de reportes - **Consumidor:** `ReportConsumer` (consumer de reportes) - **Eventos:** CREATE, UPDATE_VISIBILITY, DELETE ### `notifications_queue` (NUEVA) - **PropΓ³sito:** Eventos de cambios de estado para crear notificaciones - **Consumidor:** `NotificationConsumer` (consumer de notificaciones) - **Eventos:** UPDATE_STATUS, UPDATE_VISIBILITY ### `users_queue` - **PropΓ³sito:** Eventos de usuarios - **Consumidor:** `UserConsumer` --- ## πŸ”Œ API Endpoints de Notificaciones ### Base: `http://localhost:8002` | MΓ©todo | Endpoint | DescripciΓ³n | Auth | |--------|----------|-------------|------| | GET | `/` | Health check | No | | POST | `/notifications/` | Crear notificaciΓ³n (interno) | SΓ­ | | GET | `/notifications/{user_id}` | Obtener notificaciones del usuario | SΓ­ | | GET | `/notifications/{user_id}/unread-count` | Contar no leΓ­das | SΓ­ | | PUT | `/notifications/{notification_id}/read` | Marcar como leΓ­da | SΓ­ | | PUT | `/notifications/{user_id}/read-all` | Marcar todas como leΓ­das | SΓ­ | | DELETE | `/notifications/{notification_id}` | Eliminar notificaciΓ³n | SΓ­ | **DocumentaciΓ³n interactiva:** http://localhost:8002/docs --- ## πŸ” Seguridad y Validaciones ### Por Implementar en Frontend 1. **AutenticaciΓ³n:** - Incluir JWT token en header `Authorization: Bearer {token}` - Validar que el token no estΓ© expirado 2. **AutorizaciΓ³n:** - Backend valida que `user_id` en token === `user_id` en path - Usuario solo puede ver sus propias notificaciones 3. **Rate Limiting:** - Considerar mΓ‘ximo 1 request de polling cada 10 segundos - WebSocket es alternativa para mayor escalabilidad --- ## πŸ§ͺ Pruebas Recomendadas ### 1. Test Manual: Crear NotificaciΓ³n ```bash # Terminal 1: Iniciar el proyecto python src/main.py # Terminal 2: Test crear notificaciΓ³n curl -X POST http://localhost:8002/notifications/ \ -H "Content-Type: application/json" \ -d '{ "id_usuario": 1, "id_reporte": "test-report-123", "message": "Tu reporte ha sido actualizado" }' ``` ### 2. Test Manual: Obtener Notificaciones ```bash curl http://localhost:8002/notifications/1 \ -H "Authorization: Bearer {tu_jwt_token}" ``` ### 3. Test Manual: Cambio de Estado ```bash # Cambiar estado de reporte β†’ dispara notificaciΓ³n automΓ‘ticamente curl -X PUT http://localhost:8002/reports/{report_id}/status \ -H "Content-Type: application/json" \ -H "Authorization: Bearer {tu_jwt_token}" \ -d '{"estado": "resuelto"}' # Luego verificar que notificaciΓ³n se creΓ³: curl http://localhost:8002/notifications/1 \ -H "Authorization: Bearer {tu_jwt_token}" ``` --- ## 🐳 Comandos Docker ```bash # Levantar todos los servicios docker-compose up -d # Ver logs en tiempo real docker-compose logs -f # Ver logs especΓ­ficos de un servicio docker-compose logs -f mongodb docker-compose logs -f rabbitmq # Detener servicios docker-compose down # Verificar estado docker-compose ps ``` --- ## πŸ“‹ Arquitectura de Capas ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ PresentaciΓ³n (Frontend) β”‚ β”‚ (Implementar segΓΊn FRONTEND_NOTIFICATIONS_...) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ HTTP/REST + WebSocket (opcional) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€v────────────────────────────────┐ β”‚ API FastAPI β”‚ β”‚ β”œβ”€ /notifications/{user_id} β”‚ β”‚ β”œβ”€ /notifications/{notification_id}/read β”‚ β”‚ └─ ... (Ver endpoints arriba) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€v────────────────────────────────┐ β”‚ Capa de AplicaciΓ³n (Services) β”‚ β”‚ └─ NotificationService β”‚ β”‚ β”œβ”€ create_notification() β”‚ β”‚ β”œβ”€ get_user_notifications() β”‚ β”‚ β”œβ”€ mark_as_read() β”‚ β”‚ └─ send_report_status_notification() β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€v────────────────────────────────┐ β”‚ Capa de Dominio β”‚ β”‚ └─ Notification (dataclass) β”‚ β”‚ β”œβ”€ id_usuario β”‚ β”‚ β”œβ”€ id_reporte β”‚ β”‚ β”œβ”€ message β”‚ β”‚ β”œβ”€ fecha β”‚ β”‚ └─ read β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€v────────────────────────────────┐ β”‚ Puertos (Interfaces Abstractas) β”‚ β”‚ └─ NotificationRepository β”‚ β”‚ β”œβ”€ create() β”‚ β”‚ β”œβ”€ get_by_user() β”‚ β”‚ β”œβ”€ mark_as_read() β”‚ β”‚ └─ ... β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€v────────────────────────────────┐ β”‚ Infraestructura (Adaptadores) β”‚ β”‚ └─ NotificationRepositoryMongo β”‚ β”‚ β”œβ”€ Implementa NotificationRepository β”‚ β”‚ └─ Usa MongoDB β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸ“ˆ Escalabilidad Futura ### Fase 2 - Recomendaciones 1. **WebSocket Server:** - Implementar socket.io en FastAPI - Notificaciones push en tiempo real - Reducir latencia para usuarios conectados 2. **Cache Redis:** - Cachear conteo de no leΓ­das - Sincronizar estado entre instancias 3. **HistΓ³rico de Cambios:** - Almacenar todos los cambios de estado - Mostrar timeline en detalle de reporte 4. **Notificaciones Push:** - Integrar con Firebase Cloud Messaging - Enviar notificaciones a dispositivos mΓ³viles 5. **BΓΊsqueda Full-Text:** - Elasticsearch para buscar en notificaciones - Filtrado avanzado --- ## πŸ†˜ Troubleshooting ### Problema: "Cannot connect to MongoDB" ```bash # SoluciΓ³n: Asegurar que MongoDB estΓ© levantado docker-compose up -d mongodb # Verificar logs docker-compose logs mongodb ``` ### Problema: "RabbitMQ connection refused" ```bash # SoluciΓ³n: Asegurar que RabbitMQ estΓ© levantado docker-compose up -d rabbitmq # Verificar logs docker-compose logs rabbitmq # Acceder a management UI http://localhost:15672 (usuario: voxpopuli, pass: voxpopuli_pass) ``` ### Problema: "Notification not found" - Verificar que `id_usuario` es correcto - Verificar que JWT token pertenece al usuario - Revisar que el consumidor estΓ‘ ejecutando ### Problema: No se crean notificaciones al cambiar estado ```bash # 1. Verificar que consumidor estΓ‘ corriendo # (Debe haber thread "Notifications-Consumer" en logs) # 2. Verificar mensaje en RabbitMQ # Ir a http://localhost:15672 > Queues > notifications_queue # 3. Revisar logs del consumidor docker-compose logs notifications-consumer # Si estuviera en Docker ``` --- ## πŸ“š DocumentaciΓ³n Relacionada - **FRONTEND_NOTIFICATIONS_IMPLEMENTATION.md** - GuΓ­a completa para implementar frontend - **ARCHITECTURE.md** - Arquitectura general del proyecto - **DATABASE.md** - InformaciΓ³n sobre bases de datos - **README.md** - Setup y ejecuciΓ³n del proyecto --- ## βœ… Checklist de ImplementaciΓ³n Backend (Completado) - [x] Crear modelo de dominio `Notification` - [x] Crear interfaz `NotificationRepository` - [x] Implementar `NotificationRepositoryMongo` - [x] Crear `NotificationService` con lΓ³gica de negocio - [x] Crear esquemas Pydantic - [x] Implementar endpoints de API - [x] Crear router de notificaciones - [x] Crear app FastAPI para notificaciones - [x] Crear `NotificationConsumer` - [x] Actualizar `config.py` con nueva BD - [x] Actualizar `docker-compose.yaml` - [x] Modificar `UpdateReportStatus` para enviar eventos - [x] Actualizar `messages.py` con `UPDATE_STATUS` - [x] Actualizar `main.py` para ejecutar nueva API y consumidor - [x] Crear documentaciΓ³n detallada para frontend - [x] Crear este documento de resumen --- ## 🎯 PrΓ³ximos Pasos para Frontend 1. **Leer:** `FRONTEND_NOTIFICATIONS_IMPLEMENTATION.md` 2. **Crear:** Hook `useNotifications` con React Query 3. **Implementar:** Componente de icono de campana 4. **Agregar:** Dropdown de notificaciones 5. **Crear:** PΓ‘gina dedicada de notificaciones 6. **Integrar:** Toast notifications 7. **Implementar:** Polling cada 30 segundos 8. **Testear:** Flujo completo de usuario --- **Estado:** βœ… Completado **PrΓ³xima RevisiΓ³n:** DespuΓ©s de implementaciΓ³n de frontend **Contacto:** Development Team