# Análisis del Módulo Mail de Odoo **Módulo:** mail **Prioridad:** P0 **Mapeo MGN:** MGN-014 (Mensajería y Notificaciones) ## Descripción Módulo transversal que proporciona: - Sistema de mensajería interna - Tracking de cambios (auditoría) - Notificaciones - Followers (seguidores de registros) - Actividades programadas - Chatter UI ## Modelos Principales ### mail.thread (Mixin) **Casi todos los modelos heredan de mail.thread:** ```python class SaleOrder(models.Model): _name = 'sale.order' _inherit = ['mail.thread', 'mail.activity.mixin'] state = fields.Selection(tracking=True) # Cambios tracked amount_total = fields.Monetary(tracking=True) ``` ### mail.message (Mensajes) - Mensajes en timeline (chatter) - Tipos: notification, comment, email - Adjuntos - Followers notificados ### mail.followers (Seguidores) - Usuarios que siguen un registro - Notificaciones automáticas - Tipos de eventos suscritos ### mail.activity (Actividades) - Tareas pendientes vinculadas a registros - Recordatorios - Asignación a usuarios ## Patrones Destacables ### 1. Tracking Automático de Cambios ```python # Con tracking=True state = fields.Selection([...], tracking=True) # Odoo automáticamente crea mensaje: # "Estado cambió de 'Draft' a 'Confirmed' por John Doe" ``` ### 2. Sistema de Notificaciones ```python # Notificar a followers self.message_post( body="Orden de venta confirmada", subject="Orden #SO001", message_type='notification' ) # Todos los followers reciben notificación ``` ### 3. Followers ```python # Agregar follower self.message_subscribe(partner_ids=[partner.id]) # Los followers reciben: # - Mensajes nuevos # - Cambios en campos tracked # - Notificaciones del registro ``` ### 4. Actividades ```python # Crear actividad (recordatorio) self.activity_schedule( 'mail.mail_activity_data_call', date_deadline=fields.Date.today() + timedelta(days=7), summary='Llamar al cliente', user_id=salesperson.id ) ``` ## Mapeo a MGN-014 ### Requerimientos Funcionales **RF-NOT-001: Sistema de notificaciones** - Notificaciones en tiempo real (WebSocket) - Notificaciones por email - Centro de notificaciones en UI **RF-NOT-002: Mensajería interna** - Chat entre usuarios - Mensajes vinculados a registros - Adjuntos **RF-NOT-003: Tracking de cambios** - Auditoría automática de modificaciones - Timeline de actividad - Quién cambió qué y cuándo **RF-NOT-004: Actividades y tareas** - Recordatorios programados - Asignación a usuarios - Follow-up automático ## Implementación Recomendada MGN-014 ### Schema: notifications ```sql CREATE TABLE notifications.messages ( id SERIAL PRIMARY KEY, tenant_id INT NOT NULL, model VARCHAR(100) NOT NULL, -- 'sales.orders', 'purchase.orders' record_id INT NOT NULL, message_type VARCHAR(50), -- 'comment', 'notification', 'email' subject VARCHAR(200), body TEXT, author_id INT REFERENCES auth.users(id), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE notifications.followers ( id SERIAL PRIMARY KEY, tenant_id INT NOT NULL, model VARCHAR(100) NOT NULL, record_id INT NOT NULL, user_id INT REFERENCES auth.users(id), subscribed_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE (model, record_id, user_id) ); CREATE TABLE notifications.activities ( id SERIAL PRIMARY KEY, tenant_id INT NOT NULL, model VARCHAR(100) NOT NULL, record_id INT NOT NULL, activity_type VARCHAR(50), -- 'call', 'email', 'meeting', 'todo' summary VARCHAR(200), description TEXT, assigned_to INT REFERENCES auth.users(id), due_date DATE, completed BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE TABLE notifications.tracking ( id SERIAL PRIMARY KEY, tenant_id INT NOT NULL, model VARCHAR(100) NOT NULL, record_id INT NOT NULL, field_name VARCHAR(100), old_value TEXT, new_value TEXT, changed_by INT REFERENCES auth.users(id), changed_at TIMESTAMPTZ DEFAULT NOW() ); ``` ### Backend: Tracking Middleware ```typescript // Middleware para tracking automático export function trackingMiddleware(Model: any) { const originalUpdate = Model.update; Model.update = async function(id: number, data: any, userId: number) { // Leer valores actuales const oldRecord = await Model.findById(id); // Actualizar const updatedRecord = await originalUpdate.call(this, id, data); // Identificar cambios const changes = detectChanges(oldRecord, updatedRecord, Model.trackedFields); // Crear registros de tracking for (const change of changes) { await createTrackingRecord({ model: Model.tableName, record_id: id, field_name: change.field, old_value: change.oldValue, new_value: change.newValue, changed_by: userId }); // Notificar a followers await notifyFollowers(Model.tableName, id, { type: 'field_change', field: change.field, old: change.oldValue, new: change.newValue }); } return updatedRecord; }; } ``` ### Frontend: Notificaciones en Tiempo Real ```typescript // WebSocket para notificaciones const socket = io(WS_URL); socket.on('notification', (notification) => { // Mostrar toast toast.info(notification.message); // Actualizar contador notificationStore.incrementUnread(); // Reproducir sonido playNotificationSound(); }); ``` ## Patrón de Chatter UI **Odoo tiene un "Chatter" en cada formulario:** - Timeline de mensajes - Actividades pendientes - Formulario para escribir mensajes - Lista de followers **MGN-014 debe implementar componente similar:** ```typescript ``` ## WebSocket vs Polling **Odoo usa:** Polling (cada 30 segundos consulta nuevas notificaciones) **MGN-014 debe usar:** WebSocket (Socket.IO o native WebSockets) - Notificaciones en tiempo real - Menor carga en servidor - Mejor UX ## Aplicabilidad ⭐⭐⭐⭐⭐ - ESENCIAL El patrón de mail.thread es uno de los más valiosos de Odoo. Permite: - Auditoría completa sin código adicional - Colaboración en registros - Sistema de notificaciones unificado **Recomendación:** Implementar tracking automático desde el inicio --- **Fecha:** 2025-11-23 **Estado:** ✅ Análisis completo