import re from odoo import http from odoo.http import request class TierSendNotificationController(http.Controller): """RPC endpoint for sending a message through an external channel. Called from JS after message_post succeeds. Returns a status dict that JS uses to show a toast notification. """ @http.route( '/tier_communications/send_via_channel', methods=['POST'], type='jsonrpc', auth='user', ) def send_via_channel(self, message_id, channel_code, thread_model=None, thread_id=None): """Send an already-created mail.message through the specified external channel. Returns: { 'status': 'success' | 'error' | 'no_data', 'message': str, # human-readable status for the toast } """ message = request.env['mail.message'].browse(message_id) if not message.exists(): return {'status': 'error', 'message': 'Сообщение не найдено'} if channel_code == 'email': return _send_email(request.env, message, thread_model, thread_id) elif channel_code == 'matrix': return _send_matrix(request.env, message) else: return {'status': 'error', 'message': f'Неизвестный канал: {channel_code}'} def _send_email(env, message, thread_model, thread_id): """Send message via email. Returns status dict.""" recipient_email = None # 1. Thread partner_id if thread_model and thread_id and thread_model not in ('mail.thread', 'discuss.channel'): thread_record = env[thread_model].browse(thread_id) if thread_record.exists() and hasattr(thread_record, 'partner_id'): partner = thread_record.partner_id if partner and partner.email: recipient_email = partner.email # 2. Message partner_ids if not recipient_email and message.partner_ids: for partner in message.partner_ids: if partner.email: recipient_email = partner.email break # 3. Last incoming message email_from if not recipient_email and message.model and message.res_id: last_incoming = env['mail.message'].search([ ('model', '=', message.model), ('res_id', '=', message.res_id), ('message_type', 'in', ['email', 'comment']), ('email_from', '!=', False), ('author_id', '!=', env.user.partner_id.id), ], order='id desc', limit=1) if last_incoming and last_incoming.email_from: email_match = re.search(r'<([^>]+)>', last_incoming.email_from) recipient_email = email_match.group(1) if email_match else last_incoming.email_from # 4. discuss.channel other member if not recipient_email and thread_model == 'discuss.channel' and thread_id: channel = env['discuss.channel'].browse(thread_id) if channel.exists(): other_members = channel.channel_member_ids.filtered( lambda m: m.partner_id and m.partner_id != env.user.partner_id ) for member in other_members: if member.partner_id.email: recipient_email = member.partner_id.email break if not recipient_email: return { 'status': 'no_data', 'message': 'Не заполнен email получателя', } try: mail_values = { 'subject': message.subject or 'Сообщение из Odoo', 'body_html': message.body or '', 'email_to': recipient_email, 'email_from': env.company.email or env.user.email or '', 'auto_delete': True, } outgoing_mail = env['mail.mail'].sudo().create(mail_values) outgoing_mail.send() return { 'status': 'success', 'message': f'Сообщение отправлено на {recipient_email}', } except Exception as send_error: return { 'status': 'error', 'message': f'Ошибка отправки email: {send_error}', } def _send_matrix(env, message): """Send message via Matrix. Returns status dict.""" current_user = env.user if not hasattr(current_user, 'tier_matrix_homeserver'): return { 'status': 'no_data', 'message': 'Модуль Matrix не установлен', } homeserver_url = current_user.tier_matrix_homeserver access_token = current_user.tier_matrix_access_token room_id = current_user.tier_matrix_room_id missing_fields = [] if not homeserver_url: missing_fields.append('Homeserver URL') if not access_token: missing_fields.append('Access Token') if not room_id: missing_fields.append('Room ID') if missing_fields: return { 'status': 'no_data', 'message': f'Не заполнены данные Matrix: {", ".join(missing_fields)}', } if 'tier.channel.matrix.helper' not in env: return { 'status': 'no_data', 'message': 'Модуль Matrix не установлен', } try: env['tier.channel.matrix.helper'].channel_send_message(message, user=current_user) return { 'status': 'success', 'message': f'Сообщение отправлено в Matrix (room: {room_id})', } except Exception as send_error: return { 'status': 'error', 'message': f'Ошибка отправки Matrix: {send_error}', }