feat(odoo): add WhatsApp conversation model

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude AI
2026-01-29 22:43:06 +00:00
parent 218c137564
commit e85c9c10b5
3 changed files with 312 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
from odoo import models, fields, api
from odoo.exceptions import UserError
class WhatsAppMassWizard(models.TransientModel):
_name = 'whatsapp.mass.wizard'
_description = 'Send Mass WhatsApp Message'
account_id = fields.Many2one(
'whatsapp.account',
string='Cuenta WhatsApp',
required=True,
default=lambda self: self.env['whatsapp.account'].get_default_account(),
)
partner_ids = fields.Many2many(
'res.partner',
string='Contactos',
required=True,
)
content = fields.Text(string='Mensaje', required=True)
use_template = fields.Boolean(string='Usar Variables')
total_count = fields.Integer(
string='Total Contactos',
compute='_compute_stats',
)
valid_count = fields.Integer(
string='Con Teléfono',
compute='_compute_stats',
)
@api.depends('partner_ids')
def _compute_stats(self):
for wizard in self:
wizard.total_count = len(wizard.partner_ids)
wizard.valid_count = len(wizard.partner_ids.filtered(
lambda p: p.mobile or p.phone
))
@api.model
def default_get(self, fields_list):
res = super().default_get(fields_list)
active_ids = self.env.context.get('active_ids', [])
active_model = self.env.context.get('active_model')
if active_model == 'res.partner' and active_ids:
res['partner_ids'] = [(6, 0, active_ids)]
return res
def action_send(self):
"""Send WhatsApp to all selected partners"""
self.ensure_one()
if not self.account_id:
raise UserError('Seleccione una cuenta de WhatsApp')
sent_count = 0
failed_count = 0
for partner in self.partner_ids:
phone = partner.mobile or partner.phone
if not phone:
failed_count += 1
continue
try:
content = self.content
if self.use_template:
content = content.replace('{{name}}', partner.name or '')
content = content.replace('{{email}}', partner.email or '')
conversation = self.env['whatsapp.conversation'].find_or_create_by_phone(
phone=phone,
account_id=self.account_id.id,
contact_name=partner.name,
)
conversation.partner_id = partner
self.env['whatsapp.message'].send_message(
conversation_id=conversation.id,
content=content,
)
sent_count += 1
except Exception:
failed_count += 1
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': f'Enviados: {sent_count}, Fallidos: {failed_count}',
'type': 'success' if failed_count == 0 else 'warning',
}
}

View File

@@ -0,0 +1,78 @@
from odoo import models, fields, api
from odoo.exceptions import UserError
class WhatsAppSendWizard(models.TransientModel):
_name = 'whatsapp.send.wizard'
_description = 'Send WhatsApp Message'
partner_id = fields.Many2one('res.partner', string='Contacto')
phone = fields.Char(string='Teléfono', required=True)
account_id = fields.Many2one(
'whatsapp.account',
string='Cuenta WhatsApp',
required=True,
default=lambda self: self.env['whatsapp.account'].get_default_account(),
)
message_type = fields.Selection([
('text', 'Texto'),
('image', 'Imagen'),
('document', 'Documento'),
], string='Tipo', default='text', required=True)
content = fields.Text(string='Mensaje', required=True)
media_url = fields.Char(string='URL del Archivo')
attachment_id = fields.Many2one('ir.attachment', string='Adjunto')
res_model = fields.Char(string='Modelo Origen')
res_id = fields.Integer(string='ID Origen')
@api.onchange('attachment_id')
def _onchange_attachment_id(self):
if self.attachment_id:
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
self.media_url = f"{base_url}/web/content/{self.attachment_id.id}"
def action_send(self):
"""Send the WhatsApp message"""
self.ensure_one()
if not self.account_id:
raise UserError('Seleccione una cuenta de WhatsApp')
conversation = self.env['whatsapp.conversation'].find_or_create_by_phone(
phone=self.phone,
account_id=self.account_id.id,
contact_name=self.partner_id.name if self.partner_id else None,
)
if self.partner_id:
conversation.partner_id = self.partner_id
self.env['whatsapp.message'].send_message(
conversation_id=conversation.id,
content=self.content,
message_type=self.message_type,
media_url=self.media_url,
)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': 'Mensaje enviado correctamente',
'type': 'success',
}
}
def action_send_and_open(self):
"""Send message and open conversation"""
self.action_send()
conversation = self.env['whatsapp.conversation'].search([
('phone_number', '=', self.phone),
('account_id', '=', self.account_id.id),
], limit=1, order='id desc')
if conversation:
return conversation.action_open_chat()
return {'type': 'ir.actions.act_window_close'}