| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- from odoo import models, fields, api
- from odoo.exceptions import ValidationError
- import logging
- _logger = logging.getLogger(__name__)
- class WhatsAppComposer(models.TransientModel):
- _inherit = 'whatsapp.composer'
- # Campos para soporte básico de grupos (solo por ID string, sin Many2one)
- # La funcionalidad completa de grupos con Many2one está en whatsapp_web_groups
- recipient_type = fields.Selection([
- ('phone', 'Phone Number'),
- ('group', 'WhatsApp Group')
- ], string='Send To', default='phone', help="Choose recipient type")
-
- # Campo para ID de grupo como string
- whatsapp_group_id_char = fields.Char(string='Group ID',
- help="WhatsApp Group ID (e.g., 120363158956331133@g.us)")
-
- # Campo para mensaje libre (sin plantilla)
- body = fields.Html(string='Message Body', help="Free text message (for WhatsApp Web accounts without template)")
-
- @api.constrains('recipient_type', 'phone', 'whatsapp_group_id_char', 'wa_template_id', 'body')
- def _check_recipient_configuration(self):
- """Validar configuración de destinatario en composer"""
- for record in self:
- # Si está en contexto de skip_template_validation, saltar validaciones de plantilla
- if self.env.context.get('skip_template_validation'):
- # Solo validar configuración básica de destinatario
- if record.recipient_type == 'group' and not record.whatsapp_group_id_char:
- raise ValidationError("Please enter a Group ID when sending to groups")
- elif record.recipient_type == 'phone' and not record.phone:
- raise ValidationError("Please provide a phone number when sending to individuals")
- return # Saltar el resto de validaciones
-
- # Detectar si hay cuentas de WhatsApp Web disponibles
- whatsapp_web_accounts = record.env['whatsapp.account'].search([
- ('whatsapp_web_url', '!=', False)
- ])
- has_whatsapp_web = bool(whatsapp_web_accounts)
-
- if record.recipient_type == 'group' and not record.whatsapp_group_id_char:
- raise ValidationError("Please enter a Group ID when sending to groups")
- elif record.recipient_type == 'phone' and not record.phone:
- raise ValidationError("Please provide a phone number when sending to individuals")
-
- # Validar que haya contenido (plantilla o mensaje libre)
- if not record.wa_template_id and not record.body:
- if has_whatsapp_web:
- raise ValidationError("Please provide either a template or write a free text message")
- else:
- raise ValidationError("Template is required for WhatsApp Business API")
-
- # Si usa mensaje libre, debe haber WhatsApp Web
- if record.body and not record.wa_template_id and not has_whatsapp_web:
- raise ValidationError("Free text messages require WhatsApp Web account configuration")
-
- @api.depends('phone', 'batch_mode', 'recipient_type', 'whatsapp_group_id_char')
- def _compute_invalid_phone_number_count(self):
- """Override SOLO para casos específicos de grupos - NO interferir con funcionalidad nativa"""
- for composer in self:
- # SOLO intervenir si es un caso muy específico de grupo
- if (hasattr(composer, 'recipient_type') and composer.recipient_type == 'group'):
- composer.invalid_phone_number_count = 0
- continue
-
- # SOLO intervenir si el phone es explícitamente un ID de grupo
- if composer.phone and composer.phone.endswith('@g.us'):
- composer.invalid_phone_number_count = 0
- continue
-
- # TODOS LOS DEMÁS CASOS: usar lógica original sin modificar
- super(WhatsAppComposer, composer)._compute_invalid_phone_number_count()
-
- def action_send_whatsapp_template(self):
- """Override del método de envío SOLO para casos específicos de WhatsApp Web sin plantilla"""
-
- # SOLO intervenir si es un caso muy específico:
- # 1. No hay plantilla
- # 2. Hay mensaje libre (body)
- # 3. Es tipo grupo O hay WhatsApp Web disponible
- whatsapp_web_accounts = self.env['whatsapp.account'].search([
- ('whatsapp_web_url', '!=', False)
- ])
- has_whatsapp_web = bool(whatsapp_web_accounts)
-
- # CONDICIÓN MUY ESPECÍFICA para no interferir con funcionalidad nativa
- is_special_case = (
- not self.wa_template_id and # Sin plantilla
- self.body and # Con mensaje libre
- has_whatsapp_web and # Con WhatsApp Web disponible
- (self.recipient_type == 'group' or # Es grupo
- (hasattr(self, 'phone') and self.phone and self.phone.endswith('@g.us'))) # O es ID de grupo directo
- )
-
- if is_special_case:
- return self._send_whatsapp_web_message()
-
- # TODOS LOS DEMÁS CASOS: usar método original sin modificar
- return super().action_send_whatsapp_template()
-
- def _send_whatsapp_web_message(self):
- """Enviar mensaje WhatsApp Web sin plantilla - siguiendo lógica original"""
- records = self._get_active_records()
-
- for record in records:
- # Determinar destinatario
- if self.recipient_type == 'group':
- if self.whatsapp_group_id_char:
- mobile_number = self.whatsapp_group_id_char
- else:
- raise ValidationError("Please specify a group ID")
- else:
- mobile_number = self.phone
- if not mobile_number:
- raise ValidationError("Please provide a phone number")
-
- # Crear mail.message con adjuntos si existen (siguiendo lógica original)
- post_values = {
- 'attachment_ids': [self.attachment_id.id] if self.attachment_id else [],
- 'body': self.body,
- 'message_type': 'whatsapp_message',
- 'partner_ids': hasattr(record, '_mail_get_partners') and record._mail_get_partners()[record.id].ids or record._whatsapp_get_responsible().partner_id.ids,
- }
-
- if hasattr(records, '_message_log'):
- message = record._message_log(**post_values)
- else:
- message = self.env['mail.message'].create(
- dict(post_values, res_id=record.id, model=self.res_model,
- subtype_id=self.env['ir.model.data']._xmlid_to_res_id("mail.mt_note"))
- )
-
- # Crear mensaje WhatsApp (siguiendo estructura original)
- whatsapp_message = self.env['whatsapp.message'].create({
- 'mail_message_id': message.id,
- 'mobile_number': mobile_number,
- 'mobile_number_formatted': mobile_number,
- 'recipient_type': self.recipient_type,
- 'wa_template_id': False, # Sin plantilla
- 'wa_account_id': self._get_whatsapp_web_account().id,
- 'state': 'outgoing',
- })
-
- # Enviar mensaje usando la lógica original de _send_message
- whatsapp_message._send_message()
-
- return {'type': 'ir.actions.act_window_close'}
-
- def _prepare_whatsapp_message_values(self, record):
- """Override SOLO para agregar información de grupo - NO interferir con funcionalidad nativa"""
-
- # SIEMPRE usar lógica original primero
- values = super()._prepare_whatsapp_message_values(record)
-
- # SOLO agregar información de grupo si es caso específico
- if (hasattr(self, 'recipient_type') and self.recipient_type == 'group'):
- if self.whatsapp_group_id_char:
- values.update({
- 'recipient_type': 'group',
- 'mobile_number': self.whatsapp_group_id_char,
- 'mobile_number_formatted': self.whatsapp_group_id_char,
- })
-
- # Siempre agregar recipient_type para compatibilidad
- if not values.get('recipient_type'):
- values['recipient_type'] = 'phone'
-
- return values
-
- def _get_whatsapp_web_account(self):
- """Obtener cuenta de WhatsApp Web disponible"""
- # Primero intentar usar la cuenta de la plantilla si existe
- if self.wa_template_id and self.wa_template_id.wa_account_id and self.wa_template_id.wa_account_id.whatsapp_web_url:
- return self.wa_template_id.wa_account_id
-
- # Si no, buscar cualquier cuenta con WhatsApp Web
- account = self.env['whatsapp.account'].search([
- ('whatsapp_web_url', '!=', False)
- ], limit=1)
-
- if not account:
- raise ValidationError("No WhatsApp Web account configured")
-
- return account
-
- def _send_whatsapp_message_without_template(self, body, phone=None, group_id=None):
- """Enviar mensaje de WhatsApp sin plantilla (solo para WhatsApp Web)"""
- # Solo funciona con WhatsApp Web, no con API oficial
- if not (phone or group_id):
- raise ValidationError("Debe especificar teléfono o grupo")
-
- # Crear mensaje directamente
- message_vals = {
- 'body': body,
- 'mobile_number': group_id or phone,
- 'recipient_type': 'group' if group_id else 'phone',
- 'wa_template_id': False, # Sin plantilla
- 'state': 'outgoing',
- }
-
- # Nota: El campo whatsapp_group_id Many2one está en whatsapp_web_groups
-
- # Crear mail.message
- mail_message = self.env['mail.message'].create({
- 'body': body,
- 'message_type': 'whatsapp_message',
- })
-
- message_vals['mail_message_id'] = mail_message.id
-
- # Crear y enviar mensaje WhatsApp
- whatsapp_message = self.env['whatsapp.message'].create(message_vals)
- whatsapp_message._send_message()
-
- return whatsapp_message
|