136 lines
5.5 KiB
Python
136 lines
5.5 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.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 numbers are really unique (and don't modify values in place)
|
||
|
to_create = []
|
||
|
done = set()
|
||
|
for value in values:
|
||
|
try:
|
||
|
sanitized_value = self.env.user._phone_format(number=value['number'], raise_exception=True)
|
||
|
except UserError as err:
|
||
|
raise UserError(str(err) + _(" Please correct the number and try again.")) from err
|
||
|
if sanitized_value in done:
|
||
|
continue
|
||
|
done.add(sanitized_value)
|
||
|
to_create.append(dict(value, number=sanitized_value))
|
||
|
|
||
|
# To avoid crash during import due to unique number, return the existing records if any
|
||
|
bl_entries = {}
|
||
|
if to_create:
|
||
|
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:
|
||
|
try:
|
||
|
sanitized = self.env.user._phone_format(number=values['number'], raise_exception=True)
|
||
|
except UserError as err:
|
||
|
raise UserError(str(err) + _(" Please correct the number and try again.")) from err
|
||
|
values['number'] = sanitized
|
||
|
return super(PhoneBlackList, self).write(values)
|
||
|
|
||
|
def _search(self, domain, offset=0, limit=None, order=None, access_rights_uid=None):
|
||
|
""" Override _search in order to grep search on sanitized number field """
|
||
|
def sanitize_number(arg):
|
||
|
if isinstance(arg, (list, tuple)) and arg[0] == 'number' and isinstance(arg[2], str):
|
||
|
number = arg[2]
|
||
|
sanitized = self.env.user._phone_format(number=number)
|
||
|
if sanitized:
|
||
|
return (arg[0], arg[1], sanitized)
|
||
|
return arg
|
||
|
|
||
|
domain = [sanitize_number(item) for item in domain]
|
||
|
return super()._search(domain, offset, limit, order, access_rights_uid)
|
||
|
|
||
|
def add(self, number, message=None):
|
||
|
sanitized = self.env.user._phone_format(number=number)
|
||
|
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 = self.env.user._phone_format(number=number)
|
||
|
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)
|