mirror of
https://github.com/bringout/oca-ocb-mail.git
synced 2026-04-20 14:42:08 +02:00
19.0 vanilla
This commit is contained in:
parent
5df8c07b59
commit
daa394e8b0
2114 changed files with 564841 additions and 299642 deletions
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
import logging
|
||||
|
||||
from odoo import api, models, fields
|
||||
from odoo.addons.phone_validation.tools import phone_validation
|
||||
from odoo import api, Command, models, fields
|
||||
from odoo.addons.sms.tools.sms_tools import sms_content_to_rendered_html
|
||||
from odoo.tools import html2plaintext
|
||||
|
||||
|
|
@ -34,16 +33,17 @@ class MailThread(models.AbstractModel):
|
|||
AND msg.message_type != 'user_notification'
|
||||
GROUP BY msg.res_id
|
||||
""", {'author_id': self.env.user.partner_id.id, 'model_name': self._name, 'res_ids': tuple(self.ids)})
|
||||
res.update(self._cr.fetchall())
|
||||
res.update(self.env.cr.fetchall())
|
||||
|
||||
for record in self:
|
||||
record.message_has_sms_error = bool(res.get(record._origin.id, 0))
|
||||
|
||||
@api.model
|
||||
def _search_message_has_sms_error(self, operator, operand):
|
||||
return ['&', ('message_ids.has_sms_error', operator, operand), ('message_ids.author_id', '=', self.env.user.partner_id.id)]
|
||||
if operator != 'in':
|
||||
return NotImplemented
|
||||
return ['&', ('message_ids.has_sms_error', '=', True), ('message_ids.author_id', '=', self.env.user.partner_id.id)]
|
||||
|
||||
@api.returns('mail.message', lambda value: value.id)
|
||||
def message_post(self, *args, body='', message_type='notification', **kwargs):
|
||||
# When posting an 'SMS' `message_type`, make sure that the body is used as-is in the sms,
|
||||
# and reformat the message body for the notification (mainly making URLs clickable).
|
||||
|
|
@ -136,30 +136,25 @@ class MailThread(models.AbstractModel):
|
|||
)
|
||||
|
||||
def _notify_thread(self, message, msg_vals=False, **kwargs):
|
||||
recipients_data = super(MailThread, self)._notify_thread(message, msg_vals=msg_vals, **kwargs)
|
||||
self._notify_thread_by_sms(message, recipients_data, msg_vals=msg_vals, **kwargs)
|
||||
# Main notification method. Override to add support of sending SMS notifications.
|
||||
scheduled_date = self._is_notification_scheduled(kwargs.get('scheduled_date'))
|
||||
recipients_data = super()._notify_thread(message, msg_vals=msg_vals, **kwargs)
|
||||
if not scheduled_date:
|
||||
self._notify_thread_by_sms(message, recipients_data, msg_vals=msg_vals, **kwargs)
|
||||
return recipients_data
|
||||
|
||||
def _notify_thread_by_sms(self, message, recipients_data, msg_vals=False,
|
||||
sms_content=None, sms_numbers=None, sms_pid_to_number=None,
|
||||
resend_existing=False, put_in_queue=False, **kwargs):
|
||||
put_in_queue=False, **kwargs):
|
||||
""" Notification method: by SMS.
|
||||
|
||||
:param message: ``mail.message`` record to notify;
|
||||
:param recipients_data: list of recipients information (based on res.partner
|
||||
records), formatted like
|
||||
[{'active': partner.active;
|
||||
'id': id of the res.partner being recipient to notify;
|
||||
'groups': res.group IDs if linked to a user;
|
||||
'notif': 'inbox', 'email', 'sms' (SMS App);
|
||||
'share': partner.partner_share;
|
||||
'type': 'customer', 'portal', 'user;'
|
||||
}, {...}].
|
||||
See ``MailThread._notify_get_recipients``;
|
||||
:param msg_vals: dictionary of values used to create the message. If given it
|
||||
may be used to access values related to ``message`` without accessing it
|
||||
directly. It lessens query count in some optimized use cases by avoiding
|
||||
access message content in db;
|
||||
:param record message: <mail.message> record being notified. May be
|
||||
void as 'msg_vals' superseeds it;
|
||||
:param list recipients_data: list of recipients data based on <res.partner>
|
||||
records formatted like a list of dicts containing information. See
|
||||
``MailThread._notify_get_recipients()``;
|
||||
:param dict msg_vals: values dict used to create the message, allows to
|
||||
skip message usage and spare some queries if given;
|
||||
|
||||
:param sms_content: plaintext version of body, mainly to avoid
|
||||
conversion glitches by splitting html and plain text content formatting
|
||||
|
|
@ -167,20 +162,19 @@ class MailThread(models.AbstractModel):
|
|||
If not given, `msg_vals`'s `body` is used and converted from html to plaintext;
|
||||
:param sms_numbers: additional numbers to notify in addition to partners
|
||||
and classic recipients;
|
||||
:param pid_to_number: force a number to notify for a given partner ID
|
||||
:param sms_pid_to_number: force a number to notify for a given partner ID
|
||||
instead of taking its mobile / phone number;
|
||||
:param resend_existing: check for existing notifications to update based on
|
||||
mailed recipient, otherwise create new notifications;
|
||||
:param put_in_queue: use cron to send queued SMS instead of sending them
|
||||
directly;
|
||||
"""
|
||||
msg_vals = msg_vals or {}
|
||||
sms_pid_to_number = sms_pid_to_number if sms_pid_to_number is not None else {}
|
||||
sms_numbers = sms_numbers if sms_numbers is not None else []
|
||||
sms_create_vals = []
|
||||
sms_all = self.env['sms.sms'].sudo()
|
||||
|
||||
# pre-compute SMS data
|
||||
body = sms_content or html2plaintext(msg_vals['body'] if msg_vals and 'body' in msg_vals else message.body)
|
||||
body = sms_content or html2plaintext(msg_vals['body'] if 'body' in msg_vals else message.body)
|
||||
sms_base_vals = {
|
||||
'body': body,
|
||||
'mail_message_id': message.id,
|
||||
|
|
@ -192,21 +186,18 @@ class MailThread(models.AbstractModel):
|
|||
partner_ids = [r['id'] for r in partners_data]
|
||||
if partner_ids:
|
||||
for partner in self.env['res.partner'].sudo().browse(partner_ids):
|
||||
number = sms_pid_to_number.get(partner.id) or partner.mobile or partner.phone
|
||||
sanitize_res = phone_validation.phone_sanitize_numbers_w_record([number], partner)[number]
|
||||
number = sanitize_res['sanitized'] or number
|
||||
number = sms_pid_to_number.get(partner.id) or partner.phone
|
||||
sms_create_vals.append(dict(
|
||||
sms_base_vals,
|
||||
partner_id=partner.id,
|
||||
number=number
|
||||
number=partner._phone_format(number=number) or number,
|
||||
))
|
||||
|
||||
# notify from additional numbers
|
||||
if sms_numbers:
|
||||
sanitized = phone_validation.phone_sanitize_numbers_w_record(sms_numbers, self)
|
||||
tocreate_numbers = [
|
||||
value['sanitized'] or original
|
||||
for original, value in sanitized.items()
|
||||
self._phone_format(number=sms_number) or sms_number
|
||||
for sms_number in sms_numbers
|
||||
]
|
||||
existing_partners_numbers = {vals_dict['number'] for vals_dict in sms_create_vals}
|
||||
sms_create_vals += [dict(
|
||||
|
|
@ -218,55 +209,34 @@ class MailThread(models.AbstractModel):
|
|||
) for n in tocreate_numbers if n not in existing_partners_numbers]
|
||||
|
||||
# create sms and notification
|
||||
existing_pids, existing_numbers = [], []
|
||||
if sms_create_vals:
|
||||
sms_all |= self.env['sms.sms'].sudo().create(sms_create_vals)
|
||||
|
||||
if resend_existing:
|
||||
existing = self.env['mail.notification'].sudo().search([
|
||||
'|', ('res_partner_id', 'in', partner_ids),
|
||||
'&', ('res_partner_id', '=', False), ('sms_number', 'in', sms_numbers),
|
||||
('notification_type', '=', 'sms'),
|
||||
('mail_message_id', '=', message.id)
|
||||
])
|
||||
for n in existing:
|
||||
if n.res_partner_id.id in partner_ids and n.mail_message_id == message:
|
||||
existing_pids.append(n.res_partner_id.id)
|
||||
if not n.res_partner_id and n.sms_number in sms_numbers and n.mail_message_id == message:
|
||||
existing_numbers.append(n.sms_number)
|
||||
|
||||
notif_create_values = [{
|
||||
'author_id': message.author_id.id,
|
||||
'mail_message_id': message.id,
|
||||
'res_partner_id': sms.partner_id.id,
|
||||
'sms_number': sms.number,
|
||||
'notification_type': 'sms',
|
||||
'sms_id': sms.id,
|
||||
'sms_id_int': sms.id,
|
||||
'sms_tracker_ids': [Command.create({'sms_uuid': sms.uuid})] if sms.state == 'outgoing' else False,
|
||||
'is_read': True, # discard Inbox notification
|
||||
'notification_status': 'ready' if sms.state == 'outgoing' else 'exception',
|
||||
'failure_type': '' if sms.state == 'outgoing' else sms.failure_type,
|
||||
} for sms in sms_all if (sms.partner_id and sms.partner_id.id not in existing_pids) or (not sms.partner_id and sms.number not in existing_numbers)]
|
||||
} for sms in sms_all]
|
||||
if notif_create_values:
|
||||
self.env['mail.notification'].sudo().create(notif_create_values)
|
||||
|
||||
if existing_pids or existing_numbers:
|
||||
for sms in sms_all:
|
||||
notif = next((n for n in existing if
|
||||
(n.res_partner_id.id in existing_pids and n.res_partner_id.id == sms.partner_id.id) or
|
||||
(not n.res_partner_id and n.sms_number in existing_numbers and n.sms_number == sms.number)), False)
|
||||
if notif:
|
||||
notif.write({
|
||||
'notification_type': 'sms',
|
||||
'notification_status': 'ready',
|
||||
'sms_id': sms.id,
|
||||
'sms_number': sms.number,
|
||||
})
|
||||
|
||||
if sms_all and not put_in_queue:
|
||||
sms_all.filtered(lambda sms: sms.state == 'outgoing').send(auto_commit=False, raise_exception=False)
|
||||
sms_all.filtered(lambda sms: sms.state == 'outgoing').send(raise_exception=False)
|
||||
|
||||
return True
|
||||
|
||||
def _get_notify_valid_parameters(self):
|
||||
return super()._get_notify_valid_parameters() | {
|
||||
'put_in_queue', 'sms_numbers', 'sms_pid_to_number', 'sms_content',
|
||||
}
|
||||
|
||||
@api.model
|
||||
def notify_cancel_by_type(self, notification_type):
|
||||
super().notify_cancel_by_type(notification_type)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue