from odoo import models, fields, api import logging _logger = logging.getLogger(__name__) class WhatsAppConversation(models.Model): _name = 'whatsapp.conversation' _description = 'WhatsApp Conversation' _order = 'last_message_at desc' _rec_name = 'display_name' external_id = fields.Char(string='ID Externo', index=True) account_id = fields.Many2one( 'whatsapp.account', string='Cuenta WhatsApp', required=True, ondelete='cascade', ) partner_id = fields.Many2one( 'res.partner', string='Contacto', ondelete='set null', ) phone_number = fields.Char(string='Teléfono', required=True, index=True) contact_name = fields.Char(string='Nombre del Contacto') status = fields.Selection([ ('bot', 'Bot'), ('waiting', 'En Espera'), ('active', 'Activa'), ('resolved', 'Resuelta'), ], string='Estado', default='bot') assigned_user_id = fields.Many2one( 'res.users', string='Agente Asignado', ) last_message_at = fields.Datetime(string='Último Mensaje') last_message_preview = fields.Char( string='Último Mensaje', compute='_compute_last_message', store=True, ) message_ids = fields.One2many( 'whatsapp.message', 'conversation_id', string='Mensajes', ) message_count = fields.Integer( string='Mensajes', compute='_compute_message_count', ) display_name = fields.Char( string='Nombre', compute='_compute_display_name', store=True, ) unread_count = fields.Integer( string='No Leídos', compute='_compute_unread_count', store=True, ) @api.depends('partner_id', 'contact_name', 'phone_number') def _compute_display_name(self): for conv in self: if conv.partner_id: conv.display_name = conv.partner_id.name elif conv.contact_name: conv.display_name = conv.contact_name else: conv.display_name = conv.phone_number @api.depends('message_ids') def _compute_message_count(self): for conv in self: conv.message_count = len(conv.message_ids) @api.depends('message_ids.content') def _compute_last_message(self): for conv in self: last_msg = conv.message_ids[:1] if last_msg: content = last_msg.content or '' conv.last_message_preview = content[:50] + '...' if len(content) > 50 else content else: conv.last_message_preview = '' @api.depends('message_ids.is_read') def _compute_unread_count(self): for conv in self: conv.unread_count = len(conv.message_ids.filtered( lambda m: m.direction == 'inbound' and not m.is_read )) def action_open_chat(self): """Open chat view for this conversation""" self.ensure_one() return { 'type': 'ir.actions.act_window', 'name': self.display_name, 'res_model': 'whatsapp.conversation', 'res_id': self.id, 'view_mode': 'form', 'target': 'current', } def action_mark_resolved(self): """Mark conversation as resolved""" self.write({'status': 'resolved'}) def action_assign_to_me(self): """Assign conversation to current user""" self.write({ 'assigned_user_id': self.env.user.id, 'status': 'active', }) def action_open_send_wizard(self): """Open wizard to send WhatsApp message""" self.ensure_one() return { 'type': 'ir.actions.act_window', 'name': 'Enviar WhatsApp', 'res_model': 'whatsapp.send.wizard', 'view_mode': 'form', 'target': 'new', 'context': { 'default_phone': self.phone_number, 'default_account_id': self.account_id.id, 'default_partner_id': self.partner_id.id if self.partner_id else False, }, } def action_open_chat(self): """Open fullscreen chat interface""" self.ensure_one() return { 'type': 'ir.actions.client', 'tag': 'whatsapp_chat', 'name': self.display_name, 'context': { 'active_id': self.id, }, } def send_message_from_chat(self, message): """Send a message from the chat interface""" self.ensure_one() import requests account = self.account_id if not account or not account.api_url: raise Exception("Cuenta WhatsApp no configurada") # Send via API api_url = account.api_url.rstrip('/') response = requests.post( f"{api_url}/whatsapp/send", json={ 'account_id': account.external_id, 'phone': self.phone_number, 'message': message, }, timeout=30, ) if response.status_code != 200: raise Exception(f"Error al enviar: {response.text}") result = response.json() # Create local message record self.env['whatsapp.message'].create({ 'conversation_id': self.id, 'direction': 'outbound', 'message_type': 'text', 'content': message, 'status': 'sent', 'sent_by_id': self.env.user.id, 'external_id': result.get('message_id'), }) # Update conversation self.write({ 'last_message_at': fields.Datetime.now(), 'status': 'active' if self.status == 'bot' else self.status, }) return True @api.model def find_or_create_by_phone(self, phone, account_id, contact_name=None): """Find or create conversation by phone number""" conversation = self.search([ ('phone_number', '=', phone), ('account_id', '=', account_id), ('status', '!=', 'resolved'), ], limit=1) if not conversation: partner = self.env['res.partner'].search([ '|', ('phone', 'ilike', phone[-10:]), ('mobile', 'ilike', phone[-10:]), ], limit=1) conversation = self.create({ 'phone_number': phone, 'account_id': account_id, 'contact_name': contact_name, 'partner_id': partner.id if partner else False, }) return conversation