Extensión del modelo base de cuentas WhatsApp para soportar WhatsApp Web.
| Campo | Tipo | Descripción |
|---|---|---|
whatsapp_web_url |
Char | URL del servidor whatsapp-web.js |
get_groups()Obtiene la lista de grupos disponibles en WhatsApp Web.
Parámetros: Ninguno
Retorna: list - Lista de diccionarios con información de grupos
Ejemplo:
account = self.env['whatsapp.account'].browse(1)
groups = account.get_groups()
Respuesta esperada:
[
{
'id': {'_serialized': '120363158956331133@g.us'},
'name': 'Mi Grupo',
'members': [
{
'id': {'_serialized': '5215551234567@c.us'},
'number': '5551234567',
'name': 'Juan Pérez',
'isAdmin': False,
'isSuperAdmin': False
}
]
}
]
Extensión del modelo base de mensajes WhatsApp para soportar grupos.
| Campo | Tipo | Descripción |
|---|---|---|
recipient_type |
Selection | Tipo de destinatario: 'phone' o 'group' |
whatsapp_group_id |
Many2one | Referencia al grupo (modelo ww.group) |
final_recipient |
Char | Destinatario final calculado |
_compute_final_recipient()Calcula el destinatario final basado en el tipo de destinatario.
Parámetros: Ninguno (compute method)
Retorna: str - ID del destinatario final
_get_final_destination()Método mejorado para obtener destino final (grupo o teléfono).
Parámetros: Ninguno
Retorna: str|False - ID del destino final o False
Ejemplo:
message = self.env['whatsapp.message'].browse(1)
destination = message._get_final_destination()
_send_message(with_commit=False)Override del método de envío para soportar WhatsApp Web.
Parámetros:
with_commit (bool): Si hacer commit después del envíoRetorna: None
Ejemplo:
message = self.env['whatsapp.message'].browse(1)
message._send_message(with_commit=True)
Extensión del composer de WhatsApp para soportar grupos y mensajes libres.
| Campo | Tipo | Descripción |
|---|---|---|
recipient_type |
Selection | Tipo de destinatario: 'phone' o 'group' |
whatsapp_group_id |
Many2one | Referencia al grupo |
whatsapp_group_id_char |
Char | ID de grupo manual |
body |
Html | Mensaje libre (sin plantilla) |
_check_recipient_configuration()Valida la configuración del destinatario en el composer.
Parámetros: Ninguno (constraint method)
Retorna: None (raise ValidationError si hay error)
_compute_invalid_phone_number_count()Override para casos específicos de grupos.
Parámetros: Ninguno (compute method)
Retorna: None
_onchange_recipient_type()Limpia campos al cambiar tipo de destinatario.
Parámetros: Ninguno (onchange method)
Retorna: None
action_send_whatsapp_template()Override del método de envío para casos específicos de WhatsApp Web.
Parámetros: Ninguno
Retorna: dict - Acción de ventana o resultado del envío
_send_whatsapp_web_message()Envía mensaje WhatsApp Web sin plantilla.
Parámetros: Ninguno
Retorna: dict - Acción de cierre de ventana
Ejemplo:
composer = self.env['whatsapp.composer'].create({
'recipient_type': 'group',
'whatsapp_group_id': group.id,
'body': 'Hola grupo!'
})
result = composer._send_whatsapp_web_message()
_prepare_whatsapp_message_values(record)Override para agregar información de grupo.
Parámetros:
record (recordset): Registro relacionadoRetorna: dict - Valores para crear mensaje WhatsApp
_get_whatsapp_web_account()Obtiene cuenta de WhatsApp Web disponible.
Parámetros: Ninguno
Retorna: whatsapp.account - Cuenta WhatsApp Web
Ejemplo:
composer = self.env['whatsapp.composer'].create({})
account = composer._get_whatsapp_web_account()
_send_whatsapp_message_without_template(body, phone=None, group_id=None)Envía mensaje de WhatsApp sin plantilla.
Parámetros:
body (str): Contenido del mensajephone (str, opcional): Número de teléfonogroup_id (str, opcional): ID del grupoRetorna: whatsapp.message - Mensaje creado
Ejemplo:
composer = self.env['whatsapp.composer'].create({})
message = composer._send_whatsapp_message_without_template(
body="Mensaje de prueba",
group_id="120363158956331133@g.us"
)
# Crear composer para número individual
composer = self.env['whatsapp.composer'].create({
'recipient_type': 'phone',
'phone': '+525551234567',
'wa_template_id': template.id,
'res_model': 'res.partner',
'res_id': partner.id
})
# Enviar mensaje
result = composer.action_send_whatsapp_template()
# Crear composer para grupo
composer = self.env['whatsapp.composer'].create({
'recipient_type': 'group',
'whatsapp_group_id': group.id,
'body': '<p>Hola grupo! Este es un mensaje libre.</p>',
'res_model': 'ww.group',
'res_id': group.id
})
# Enviar mensaje
result = composer.action_send_whatsapp_template()
# Crear attachment
attachment = self.env['ir.attachment'].create({
'name': 'documento.pdf',
'type': 'binary',
'datas': base64.b64encode(pdf_content),
'mimetype': 'application/pdf'
})
# Crear composer con adjunto
composer = self.env['whatsapp.composer'].create({
'recipient_type': 'phone',
'phone': '+525551234567',
'body': 'Adjunto documento importante',
'attachment_id': attachment.id,
'res_model': 'res.partner',
'res_id': partner.id
})
# Enviar mensaje
result = composer.action_send_whatsapp_template()
# Obtener cuenta WhatsApp Web
account = self.env['whatsapp.account'].search([
('whatsapp_web_url', '!=', False)
], limit=1)
# Obtener grupos
groups = account.get_groups()
# Procesar grupos
for group_data in groups:
group_id = group_data['id']['_serialized']
group_name = group_data['name']
members = group_data.get('members', [])
print(f"Grupo: {group_name} ({group_id})")
print(f"Miembros: {len(members)}")
# Crear mensaje directamente
message = self.env['whatsapp.message'].create({
'recipient_type': 'group',
'whatsapp_group_id': group.id,
'mobile_number': group.whatsapp_web_id,
'body': 'Mensaje directo al grupo',
'wa_account_id': account.id,
'state': 'outgoing'
})
# Enviar mensaje
message._send_message(with_commit=True)
{
"_data": {
"id": {
"_serialized": "3EB0C767D26A3D1B7B4A_5215551234567@c.us"
}
}
}
[
{
"id": {
"_serialized": "120363158956331133@g.us"
},
"name": "Mi Grupo de Trabajo",
"description": "Grupo para coordinación de proyectos",
"members": [
{
"id": {
"_serialized": "5215551234567@c.us"
},
"number": "5551234567",
"name": "Juan Pérez",
"pushname": "Juan",
"isAdmin": true,
"isSuperAdmin": false
},
{
"id": {
"_serialized": "5215557654321@c.us"
},
"number": "5557654321",
"name": "María García",
"pushname": "María",
"isAdmin": false,
"isSuperAdmin": false
}
],
"messages": [
{
"id": {
"_serialized": "3EB0C767D26A3D1B7B4A"
},
"body": "Hola grupo!",
"author": "5215551234567@c.us",
"timestamp": 1640995200,
"hasQuotedMsg": false
}
]
}
]
{
"error": "Método no implementado",
"code": 501
}
| Código | Descripción |
|---|---|
| 200 | Petición exitosa |
| 400 | Error en los parámetros |
| 401 | No autorizado |
| 404 | Endpoint no encontrado |
| 500 | Error interno del servidor |
| 501 | Método no implementado |
+525551234567, 5551234567, 52155512345675215551234567@c.us120363158956331133@g.usfrom odoo.exceptions import ValidationError
try:
composer.action_send_whatsapp_template()
except ValidationError as e:
print(f"Error de validación: {e}")
import requests
try:
response = requests.post(url, data=payload, headers=headers)
except requests.exceptions.ConnectionError:
print("Error de conexión con el servidor WhatsApp Web")
import logging
_logger = logging.getLogger(__name__)
# Log de envío exitoso
_logger.info('WHATSAPP WEB SEND MESSAGE: %s', url)
# Log de error
_logger.error("Error en la petición de groups: %s", response.text)
# Configurar timeout para requests
import requests
response = requests.post(
url,
data=payload,
headers=headers,
timeout=30 # 30 segundos
)
El módulo incluye delays aleatorios entre envíos:
import time
import random
# Delay aleatorio entre 3-7 segundos
time.sleep(random.randint(3, 7))