|
@@ -1,661 +0,0 @@
|
|
|
-# 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.
|
|
|
|
|
-
|
|
|