TROUBLESHOOTING.md 18 KB

Guía de Solución de Problemas - WhatsApp Web Integration

Índice

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:

# 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
# 2. Verificar configuración de cuenta
account = env['whatsapp.account'].search([], limit=1)
print(f"URL configurada: {account.whatsapp_web_url}")
# 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:

# 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:

# 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:

# 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:

# 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:

# Deshabilitar verificación SSL (solo para desarrollo)
import requests
requests.packages.urllib3.disable_warnings()

response = requests.post(url, json=payload, verify=False)
# 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:

# 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:

// 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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:

# 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

# 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

# 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

# Acceder al shell de Odoo
cd /var/odoo/mcteam.run
sudo -u odoo venv/bin/python3 src/odoo-bin shell -c odoo.conf
# 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

# 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

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.