RATIONALE Purpose of this commit is to be explicit in subtype chosen when invoking the message composer / calling message_post. As default value may not always be clear, better be explicit in case the composer default value changes. SPECIFICATIONS Add explicit references to subtype when it is not obvious what will be the final subtype, notably when using helpers (post_with_view or template which uses the composer that is not crystal clear in its subtype management). In this commit we also add support of XMLID-based subtype when invoking the composer. A ``default_subtype_xmlid`` context key is transformed into a ``default_subtype_id``, to be used notably in JS where we cannot easily use a ``ref``-like statement. Post API now also supports 'subytpe_xmlid' argument allowing to give the xml id and ease calling the methods. Use ``_xmlid_to_res_id`` to get directly the ID of subtypes in order to avoid useless queries from ``ref`` that does an exists. Also remove useless values given to post API, notably author_id that is by default the current users' partner. Task-2710804 (Mail: Clean MailThread Posting API) Part-of: odoo/odoo#99482
142 lines
6.0 KiB
Python
142 lines
6.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import logging
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.addons.phone_validation.tools import phone_validation
|
|
from odoo.exceptions import UserError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class PhoneBlackList(models.Model):
|
|
""" Blacklist of phone numbers. Used to avoid sending unwanted messages to people. """
|
|
_name = 'phone.blacklist'
|
|
_inherit = ['mail.thread']
|
|
_description = 'Phone Blacklist'
|
|
_rec_name = 'number'
|
|
|
|
number = fields.Char(string='Phone Number', required=True, tracking=True, help='Number should be E164 formatted')
|
|
active = fields.Boolean(default=True, tracking=True)
|
|
|
|
_sql_constraints = [
|
|
('unique_number', 'unique (number)', 'Number already exists')
|
|
]
|
|
|
|
@api.model_create_multi
|
|
def create(self, values):
|
|
# First of all, extract values to ensure emails are really unique (and don't modify values in place)
|
|
to_create = []
|
|
done = set()
|
|
for value in values:
|
|
number = value['number']
|
|
sanitized_values = phone_validation.phone_sanitize_numbers_w_record([number], self.env.user)[number]
|
|
sanitized = sanitized_values['sanitized']
|
|
if not sanitized:
|
|
raise UserError(sanitized_values['msg'] + _(" Please correct the number and try again."))
|
|
if sanitized in done:
|
|
continue
|
|
done.add(sanitized)
|
|
to_create.append(dict(value, number=sanitized))
|
|
|
|
""" To avoid crash during import due to unique email, return the existing records if any """
|
|
sql = '''SELECT number, id FROM phone_blacklist WHERE number = ANY(%s)'''
|
|
numbers = [v['number'] for v in to_create]
|
|
self._cr.execute(sql, (numbers,))
|
|
bl_entries = dict(self._cr.fetchall())
|
|
to_create = [v for v in to_create if v['number'] not in bl_entries]
|
|
|
|
results = super(PhoneBlackList, self).create(to_create)
|
|
return self.env['phone.blacklist'].browse(bl_entries.values()) | results
|
|
|
|
def write(self, values):
|
|
if 'number' in values:
|
|
number = values['number']
|
|
sanitized_values = phone_validation.phone_sanitize_numbers_w_record([number], self.env.user)[number]
|
|
sanitized = sanitized_values['sanitized']
|
|
if not sanitized:
|
|
raise UserError(sanitized_values['msg'] + _(" Please correct the number and try again."))
|
|
values['number'] = sanitized
|
|
return super(PhoneBlackList, self).write(values)
|
|
|
|
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
|
|
""" Override _search in order to grep search on sanitized number field """
|
|
if args:
|
|
new_args = []
|
|
for arg in args:
|
|
if isinstance(arg, (list, tuple)) and arg[0] == 'number' and isinstance(arg[2], str):
|
|
number = arg[2]
|
|
sanitized = phone_validation.phone_sanitize_numbers_w_record([number], self.env.user)[number]['sanitized']
|
|
if sanitized:
|
|
new_args.append([arg[0], arg[1], sanitized])
|
|
else:
|
|
new_args.append(arg)
|
|
else:
|
|
new_args.append(arg)
|
|
else:
|
|
new_args = args
|
|
return super(PhoneBlackList, self)._search(new_args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
|
|
|
|
def add(self, number, message=None):
|
|
sanitized = phone_validation.phone_sanitize_numbers_w_record([number], self.env.user)[number]['sanitized']
|
|
return self._add([sanitized], message=message)
|
|
|
|
def _add(self, numbers, message=None):
|
|
""" Add or re activate a phone blacklist entry.
|
|
|
|
:param numbers: list of sanitized numbers """
|
|
records = self.env["phone.blacklist"].with_context(active_test=False).search([('number', 'in', numbers)])
|
|
todo = [n for n in numbers if n not in records.mapped('number')]
|
|
if records:
|
|
if message:
|
|
records._track_set_log_message(message)
|
|
records.action_unarchive()
|
|
if todo:
|
|
new_records = self.create([{'number': n} for n in todo])
|
|
if message:
|
|
for record in new_records:
|
|
record.with_context(mail_create_nosubscribe=True).message_post(
|
|
body=message,
|
|
subtype_xmlid='mail.mt_note',
|
|
)
|
|
records += new_records
|
|
return records
|
|
|
|
def remove(self, number, message=None):
|
|
sanitized = phone_validation.phone_sanitize_numbers_w_record([number], self.env.user)[number]['sanitized']
|
|
return self._remove([sanitized], message=message)
|
|
|
|
def _remove(self, numbers, message=None):
|
|
""" Add de-activated or de-activate a phone blacklist entry.
|
|
|
|
:param numbers: list of sanitized numbers """
|
|
records = self.env["phone.blacklist"].with_context(active_test=False).search([('number', 'in', numbers)])
|
|
todo = [n for n in numbers if n not in records.mapped('number')]
|
|
if records:
|
|
if message:
|
|
records._track_set_log_message(message)
|
|
records.action_archive()
|
|
if todo:
|
|
new_records = self.create([{'number': n, 'active': False} for n in todo])
|
|
if message:
|
|
for record in new_records:
|
|
record.with_context(mail_create_nosubscribe=True).message_post(
|
|
body=message,
|
|
subtype_xmlid='mail.mt_note',
|
|
)
|
|
records += new_records
|
|
return records
|
|
|
|
def phone_action_blacklist_remove(self):
|
|
return {
|
|
'name': 'Are you sure you want to unblacklist this Phone Number?',
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'form',
|
|
'res_model': 'phone.blacklist.remove',
|
|
'target': 'new',
|
|
}
|
|
|
|
def action_add(self):
|
|
self.add(self.number)
|