# Guía de Solución de Problemas - WhatsApp Web Integration ## Índice - [Problemas de Configuración](#problemas-de-configuración) - [Problemas de Conexión](#problemas-de-conexión) - [Problemas de Envío de Mensajes](#problemas-de-envío-de-mensajes) - [Problemas de Grupos](#problemas-de-grupos) - [Problemas de Sincronización](#problemas-de-sincronización) - [Problemas de Rendimiento](#problemas-de-rendimiento) - [Logs y Debugging](#logs-y-debugging) ## Problemas de Configuración ### Error: "No WhatsApp Web account configured" **Síntomas:** - Mensaje de error al intentar enviar mensajes - No se pueden configurar grupos **Causas:** 1. No se ha configurado la URL de WhatsApp Web en la cuenta 2. La cuenta WhatsApp no tiene el campo `whatsapp_web_url` configurado 3. El módulo `whatsapp_web` no está instalado **Soluciones:** ```bash # 1. Verificar instalación del módulo cd /var/odoo/mcteam.run sudo -u odoo venv/bin/python3 src/odoo-bin shell -c odoo.conf # En el shell de Odoo: env['ir.module.module'].search([('name', '=', 'whatsapp_web')]).state ``` ```python # 2. Verificar configuración de cuenta account = env['whatsapp.account'].search([], limit=1) print(f"URL configurada: {account.whatsapp_web_url}") ``` ```bash # 3. Configurar cuenta manualmente desde base de datos su - postgres -c "psql stg2.mcteam.run -c \"UPDATE whatsapp_account SET whatsapp_web_url = 'https://tu-servidor.com/api' WHERE id = 1;\" | cat" ``` ### Error: "Template is required for WhatsApp Business API" **Síntomas:** - No se pueden enviar mensajes libres (sin plantilla) - Error al usar composer sin plantilla **Causas:** 1. No hay cuentas WhatsApp Web configuradas 2. Se está intentando usar mensaje libre con API oficial **Soluciones:** ```python # Verificar cuentas WhatsApp Web disponibles accounts = env['whatsapp.account'].search([('whatsapp_web_url', '!=', False)]) print(f"Cuentas WhatsApp Web: {len(accounts)}") # Si no hay cuentas, configurar una account = env['whatsapp.account'].search([], limit=1) account.write({'whatsapp_web_url': 'https://tu-servidor.com/api'}) ``` ### Error: "Invalid recipient configuration" **Síntomas:** - Error al seleccionar destinatario en composer - Validación falla al enviar mensajes **Causas:** 1. Tipo de destinatario no coincide con datos proporcionados 2. Falta información requerida (teléfono o grupo) **Soluciones:** ```python # Verificar configuración de destinatario composer = env['whatsapp.composer'].browse(composer_id) print(f"Tipo destinatario: {composer.recipient_type}") print(f"Teléfono: {composer.phone}") print(f"Grupo: {composer.whatsapp_group_id}") # Corregir configuración if composer.recipient_type == 'group' and not composer.whatsapp_group_id: # Seleccionar grupo o cambiar a teléfono composer.write({'recipient_type': 'phone'}) ``` ## Problemas de Conexión ### Error: "Connection refused" o timeout **Síntomas:** - Timeouts en peticiones HTTP - Error de conexión al servidor whatsapp-web.js **Diagnóstico:** ```bash # 1. Verificar conectividad desde servidor Odoo curl -X POST https://tu-servidor-whatsapp.com/api \ -H "Content-Type: application/json" \ -d '{"method": "ping", "args": []}' # 2. Verificar logs del servidor whatsapp-web.js tail -f /ruta/logs/whatsapp-web.log ``` **Soluciones:** ```python # 1. Verificar URL en configuración account = env['whatsapp.account'].search([('whatsapp_web_url', '!=', False)], limit=1) print(f"URL configurada: {account.whatsapp_web_url}") # 2. Probar conectividad desde Odoo import requests try: response = requests.post(account.whatsapp_web_url, json={"method": "ping", "args": []}, timeout=10) print(f"Respuesta: {response.status_code}") except Exception as e: print(f"Error de conexión: {e}") ``` ### Error: "Invalid SSL certificate" **Síntomas:** - Error SSL al conectar con servidor HTTPS - Certificado no válido **Soluciones:** ```python # Deshabilitar verificación SSL (solo para desarrollo) import requests requests.packages.urllib3.disable_warnings() response = requests.post(url, json=payload, verify=False) ``` ```bash # Actualizar certificados del sistema sudo apt-get update sudo apt-get install ca-certificates ``` ### Error: "Method not implemented" **Síntomas:** - El servidor responde pero no implementa métodos requeridos - Error 501 en peticiones **Diagnóstico:** ```bash # Verificar métodos implementados en el servidor curl -X POST https://tu-servidor.com/api \ -H "Content-Type: application/json" \ -d '{"method": "getGroups", "args": []}' ``` **Soluciones:** ```javascript // Implementar método getGroups en servidor whatsapp-web.js app.post('/', async (req, res) => { const { method, args } = req.body; if (method === 'getGroups') { try { const chats = await client.getChats(); const groups = chats.filter(chat => chat.isGroup); res.json(groups); } catch (error) { res.status(500).json({error: error.message}); } } }); ``` ## Problemas de Envío de Mensajes ### Error: "Message not sent" **Síntomas:** - Mensajes quedan en estado "outgoing" - No se reciben mensajes en WhatsApp **Diagnóstico:** ```python # Verificar estado de mensajes messages = env['whatsapp.message'].search([ ('state', '=', 'outgoing'), ('create_date', '>', '2024-01-01') ]) for msg in messages: print(f"Mensaje {msg.id}: {msg.state} - {msg.mobile_number}") ``` **Soluciones:** ```python # 1. Verificar configuración de cuenta message = env['whatsapp.message'].browse(message_id) print(f"Cuenta: {message.wa_account_id.name}") print(f"URL: {message.wa_account_id.whatsapp_web_url}") # 2. Reintentar envío message._send_message(with_commit=True) # 3. Verificar formato de número print(f"Número original: {message.mobile_number}") formatted = message._whatsapp_phone_format() print(f"Número formateado: {formatted}") ``` ### Error: "Invalid phone number format" **Síntomas:** - Números no se formatean correctamente - Error en validación de teléfonos **Diagnóstico:** ```python # Verificar formateo de números message = env['whatsapp.message'].browse(message_id) original = message.mobile_number formatted = message._whatsapp_phone_format() print(f"Original: {original}") print(f"Formateado: {formatted}") ``` **Soluciones:** ```python # Corregir formato manualmente def format_phone_number(number): # Limpiar número clean = number.replace(' ', '').replace('+', '').replace('-', '') # Aplicar reglas de formateo if clean.startswith("52") and len(clean) == 12: clean = "521" + clean[2:] elif len(clean) == 10: clean = "521" + clean return clean + '@c.us' # Aplicar corrección message.write({ 'mobile_number': format_phone_number(message.mobile_number) }) ``` ### Error: "Attachment upload failed" **Síntomas:** - Adjuntos no se envían - Error al procesar archivos **Diagnóstico:** ```python # Verificar adjunto attachment = env['ir.attachment'].browse(attachment_id) print(f"Nombre: {attachment.name}") print(f"Tipo: {attachment.mimetype}") print(f"Tamaño: {attachment.file_size}") print(f"Datos: {len(attachment.raw) if attachment.raw else 'No hay datos'}") ``` **Soluciones:** ```python # 1. Verificar tamaño de archivo (límite WhatsApp: 100MB) if attachment.file_size > 100 * 1024 * 1024: print("Archivo demasiado grande") # 2. Verificar tipo MIME valid_types = ['image/', 'video/', 'audio/', 'application/pdf', 'text/'] if not any(attachment.mimetype.startswith(t) for t in valid_types): print(f"Tipo de archivo no soportado: {attachment.mimetype}") # 3. Regenerar datos del archivo attachment.write({'raw': base64.b64encode(file_content)}) ``` ## Problemas de Grupos ### Error: "Group not found" **Síntomas:** - Grupos no aparecen en la lista - Error al seleccionar grupo **Diagnóstico:** ```python # Verificar grupos disponibles groups = env['ww.group'].search([]) print(f"Grupos en base de datos: {len(groups)}") # Verificar sincronización account = env['whatsapp.account'].search([('whatsapp_web_url', '!=', False)], limit=1) api_groups = account.get_groups() print(f"Grupos desde API: {len(api_groups)}") ``` **Soluciones:** ```python # 1. Sincronizar grupos manualmente env['ww.group'].sync_ww_contacts_groups() # 2. Verificar respuesta de API for group_data in api_groups: print(f"Grupo API: {group_data.get('name')} - {group_data.get('id', {}).get('_serialized')}") # 3. Crear grupo manualmente si es necesario group = env['ww.group'].create({ 'name': 'Mi Grupo', 'whatsapp_web_id': '120363158956331133@g.us', 'whatsapp_account_id': account.id }) ``` ### Error: "No members in group" **Síntomas:** - Grupos sin contactos - Canales no se crean **Diagnóstico:** ```python # Verificar miembros de grupo group = env['ww.group'].browse(group_id) print(f"Contactos en grupo: {len(group.contact_ids)}") # Verificar datos de API account = group.whatsapp_account_id api_groups = account.get_groups() for api_group in api_groups: if api_group['id']['_serialized'] == group.whatsapp_web_id: members = api_group.get('members', []) print(f"Miembros en API: {len(members)}") break ``` **Soluciones:** ```python # 1. Sincronizar contactos del grupo group.write({'contact_ids': [(6, 0, contact_ids)]}) # 2. Crear contactos si no existen for member in members: contact = env['res.partner'].search([ ('whatsapp_web_id', '=', member['id']['_serialized']) ]) if not contact: contact = env['res.partner'].create({ 'name': member.get('name', 'Sin nombre'), 'mobile': member.get('number', ''), 'whatsapp_web_id': member['id']['_serialized'] }) contact_ids.append(contact.id) ``` ## Problemas de Sincronización ### Error: "Sync failed" o timeout **Síntomas:** - Sincronización se interrumpe - Timeouts en operaciones largas **Diagnóstico:** ```python # Verificar logs de sincronización import logging _logger = logging.getLogger(__name__) # Ejecutar sincronización con logging detallado try: env['ww.group'].sync_ww_contacts_groups() except Exception as e: _logger.error(f"Error en sincronización: {e}") ``` **Soluciones:** ```python # 1. Sincronizar en lotes pequeños def sync_in_batches(batch_size=5): accounts = env['whatsapp.account'].search([('whatsapp_web_url', '!=', False)]) for account in accounts: groups_data = account.get_groups() for i in range(0, len(groups_data), batch_size): batch = groups_data[i:i + batch_size] process_batch(batch, account) env.cr.commit() # Commit después de cada lote # 2. Aumentar timeout de requests import requests response = requests.post(url, json=payload, timeout=60) ``` ### Error: "Duplicate contacts" **Síntomas:** - Contactos duplicados en grupos - Constraint violations **Diagnóstico:** ```python # Buscar contactos duplicados contacts = env['res.partner'].search([ ('whatsapp_web_id', '!=', False) ]) # Verificar duplicados por número mobile_counts = {} for contact in contacts: if contact.mobile: mobile_counts[contact.mobile] = mobile_counts.get(contact.mobile, 0) + 1 duplicates = {k: v for k, v in mobile_counts.items() if v > 1} print(f"Duplicados por móvil: {duplicates}") ``` **Soluciones:** ```python # 1. Fusionar contactos duplicados def merge_duplicate_contacts(): contacts = env['res.partner'].search([('whatsapp_web_id', '!=', False)]) for contact in contacts: if contact.mobile and len(contact.mobile) >= 10: last_10 = contact.mobile[-10:] duplicates = env['res.partner'].search([ ('mobile', 'like', '%' + last_10), ('id', '!=', contact.id) ]) if duplicates: # Fusionar en el primer contacto for dup in duplicates: dup.unlink() # 2. Limpiar relaciones duplicadas def cleanup_duplicate_relations(): relations = env['ww.group_contact_rel'].search([]) for rel in relations: duplicates = env['ww.group_contact_rel'].search([ ('group_id', '=', rel.group_id.id), ('contact_id', '=', rel.contact_id.id), ('id', '!=', rel.id) ]) if duplicates: duplicates.unlink() ``` ## Problemas de Rendimiento ### Error: "Memory limit exceeded" **Síntomas:** - Procesos se terminan por falta de memoria - Sincronización falla con muchos datos **Soluciones:** ```python # 1. Procesar en chunks más pequeños def process_large_dataset(data, chunk_size=100): for i in range(0, len(data), chunk_size): chunk = data[i:i + chunk_size] process_chunk(chunk) env.cr.commit() # Commit frecuente gc.collect() # Liberar memoria # 2. Usar iteradores en lugar de listas def process_contacts_efficiently(): contacts = env['res.partner'].search([('whatsapp_web_id', '!=', False)]) for contact in contacts: process_contact(contact) if contact.id % 100 == 0: # Commit cada 100 registros env.cr.commit() ``` ### Error: "Database timeout" **Síntomas:** - Operaciones de base de datos timeout - Transacciones muy largas **Soluciones:** ```python # 1. Usar transacciones más cortas def sync_with_short_transactions(): accounts = env['whatsapp.account'].search([]) for account in accounts: with env.cr.savepoint(): # Transacción por cuenta sync_account_groups(account) env.cr.commit() # 2. Deshabilitar autocommit para operaciones masivas def bulk_operations(): env.cr.autocommit = False try: # Operaciones masivas bulk_create_contacts() bulk_update_groups() env.cr.commit() except Exception: env.cr.rollback() raise finally: env.cr.autocommit = True ``` ## Logs y Debugging ### Configurar Logging Detallado ```python # Configurar logging en código import logging _logger = logging.getLogger(__name__) # Logging detallado para debugging _logger.setLevel(logging.DEBUG) def debug_sync_process(): _logger.info("Iniciando sincronización") try: # Proceso de sincronización result = env['ww.group'].sync_ww_contacts_groups() _logger.info(f"Sincronización completada: {result}") except Exception as e: _logger.error(f"Error en sincronización: {e}", exc_info=True) ``` ### Verificar Logs del Sistema ```bash # Ver logs de Odoo en tiempo real tail -f /var/odoo/stg2.mcteam.run/logs/odoo-server.log | grep -i "whatsapp" # Filtrar por módulo específico tail -f /var/odoo/stg2.mcteam.run/logs/odoo-server.log | grep -i "whatsapp_web" # Buscar errores específicos grep -i "error\|exception\|traceback" /var/odoo/stg2.mcteam.run/logs/odoo-server.log | grep -i "whatsapp" ``` ### Debug desde Shell de Odoo ```bash # Acceder al shell de Odoo cd /var/odoo/mcteam.run sudo -u odoo venv/bin/python3 src/odoo-bin shell -c odoo.conf ``` ```python # En el shell de Odoo # Verificar estado de módulos modules = env['ir.module.module'].search([('name', 'ilike', 'whatsapp')]) for module in modules: print(f"{module.name}: {module.state}") # Verificar configuración accounts = env['whatsapp.account'].search([]) for account in accounts: print(f"Cuenta: {account.name}") print(f"URL: {account.whatsapp_web_url}") print(f"Activa: {account.active}") # Probar conectividad import requests account = accounts[0] try: response = requests.post(account.whatsapp_web_url, json={"method": "ping", "args": []}, timeout=10) print(f"Respuesta: {response.status_code}") except Exception as e: print(f"Error: {e}") ``` ### Debug de Base de Datos ```bash # Verificar registros en base de datos su - postgres -c "psql stg2.mcteam.run -c \"SELECT COUNT(*) FROM ww_group;\" | cat" # Verificar configuración de cuentas su - postgres -c "psql stg2.mcteam.run -c \"SELECT name, whatsapp_web_url FROM whatsapp_account;\" | cat" # Verificar mensajes pendientes su - postgres -c "psql stg2.mcteam.run -c \"SELECT COUNT(*) FROM whatsapp_message WHERE state = 'outgoing';\" | cat" ``` ## Herramientas de Diagnóstico ### Script de Diagnóstico Completo ```python def diagnose_whatsapp_web(): """Script completo de diagnóstico""" print("=== DIAGNÓSTICO WHATSAPP WEB ===") # 1. Verificar módulos print("\n1. Verificando módulos...") modules = env['ir.module.module'].search([('name', 'ilike', 'whatsapp')]) for module in modules: print(f" {module.name}: {module.state}") # 2. Verificar cuentas print("\n2. Verificando cuentas...") accounts = env['whatsapp.account'].search([]) for account in accounts: print(f" {account.name}: {account.whatsapp_web_url or 'Sin URL'}") # 3. Verificar grupos print("\n3. Verificando grupos...") groups = env['ww.group'].search([]) print(f" Total grupos: {len(groups)}") for group in groups: print(f" {group.name}: {len(group.contact_ids)} contactos") # 4. Verificar mensajes print("\n4. Verificando mensajes...") messages = env['whatsapp.message'].search([]) print(f" Total mensajes: {len(messages)}") outgoing = messages.filtered(lambda m: m.state == 'outgoing') print(f" Pendientes: {len(outgoing)}") # 5. Probar conectividad print("\n5. Probando conectividad...") web_account = accounts.filtered(lambda a: a.whatsapp_web_url) if web_account: try: import requests response = requests.post(web_account[0].whatsapp_web_url, json={"method": "ping", "args": []}, timeout=10) print(f" Conectividad: OK ({response.status_code})") except Exception as e: print(f" Conectividad: ERROR - {e}") else: print(" Conectividad: No hay cuentas WhatsApp Web configuradas") # Ejecutar diagnóstico diagnose_whatsapp_web() ``` Este script proporciona una visión completa del estado del sistema y ayuda a identificar problemas comunes.