Files
WhatsAppCentralizado/odoo_whatsapp_hub/models/whatsapp_conversation.py
Claude AI 28592254b2 fix(odoo): agregar store=True a campos computados
- unread_count: necesario para filtros de búsqueda
- last_message_preview: necesario para vistas

Campos computados sin store=True no pueden usarse en dominios de filtros.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 00:38:13 +00:00

142 lines
4.3 KiB
Python

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',
})
@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