[FIX] phone_validation: correctly use phone fields when searching on phone/mobile
Currently the search methods defined on ``phone_mobile_search`` field forces the usage of ``phone`` and ``mobile`` fields on model. This currently works on models using by default this search field (lead and partner). However this breaks on any model not having those two fields and inheriting from the 'mail.thread.phone' mixin. In this commit we use the result of ``_phone_get_number_fields`` to know which fields to use in the SQL query. Tests are added to ensure it works as intended. Task-3012789 X-original-commit: 6b235868da6fed1b2a0eaa7a25dc2202c6fefaa0 Part-of: odoo/odoo#104111
This commit is contained in:
@@ -248,6 +248,12 @@ msgstr ""
|
||||
msgid "Messages"
|
||||
msgstr ""
|
||||
|
||||
#. module: phone_validation
|
||||
#: code:addons/phone_validation/models/mail_thread_phone.py:0
|
||||
#, python-format
|
||||
msgid "Missing definition of phone fields."
|
||||
msgstr ""
|
||||
|
||||
#. module: phone_validation
|
||||
#: model:ir.model.constraint,message:phone_validation.constraint_phone_blacklist_unique_number
|
||||
msgid "Number already exists"
|
||||
|
||||
@@ -6,6 +6,7 @@ import re
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.phone_validation.tools import phone_validation
|
||||
from odoo.exceptions import AccessError, UserError
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class PhoneMixin(models.AbstractModel):
|
||||
@@ -47,6 +48,13 @@ class PhoneMixin(models.AbstractModel):
|
||||
phone_mobile_search = fields.Char("Phone/Mobile", store=False, search='_search_phone_mobile_search')
|
||||
|
||||
def _search_phone_mobile_search(self, operator, value):
|
||||
phone_fields = [
|
||||
fname for fname in self._phone_get_number_fields()
|
||||
if fname in self._fields and self._fields[fname].store
|
||||
]
|
||||
if not phone_fields:
|
||||
raise UserError(_('Missing definition of phone fields.'))
|
||||
|
||||
value = value.strip()
|
||||
if len(value) < 3:
|
||||
raise UserError(_('Please enter at least 3 characters when searching a Phone/Mobile number.'))
|
||||
@@ -55,39 +63,35 @@ class PhoneMixin(models.AbstractModel):
|
||||
if value.startswith('+') or value.startswith('00'):
|
||||
# searching on +32485112233 should also finds 0032485112233 (and vice versa)
|
||||
# we therefore remove it from input value and search for both of them in db
|
||||
where_str = ' OR '.join(
|
||||
f"""model.{phone_field} IS NOT NULL AND (
|
||||
REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') ILIKE %s OR
|
||||
REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') ILIKE %s
|
||||
)"""
|
||||
for phone_field in phone_fields
|
||||
)
|
||||
query = f"""
|
||||
SELECT model.id
|
||||
FROM {self._table} model
|
||||
WHERE
|
||||
model.phone IS NOT NULL AND (
|
||||
REGEXP_REPLACE(model.phone, %s, '', 'g') ILIKE %s OR
|
||||
REGEXP_REPLACE(model.phone, %s, '', 'g') ILIKE %s
|
||||
) OR
|
||||
model.mobile IS NOT NULL AND (
|
||||
REGEXP_REPLACE(model.mobile, %s, '', 'g') ILIKE %s OR
|
||||
REGEXP_REPLACE(model.mobile, %s, '', 'g') ILIKE %s
|
||||
);
|
||||
WHERE {where_str};
|
||||
"""
|
||||
term = re.sub(pattern, '', value[1 if value.startswith('+') else 2:]) + '%'
|
||||
self._cr.execute(query, (
|
||||
pattern, '00' + term,
|
||||
pattern, '+' + term,
|
||||
pattern, '00' + term,
|
||||
pattern, '+' + term
|
||||
))
|
||||
self._cr.execute(
|
||||
query,
|
||||
(pattern, '00' + term, pattern, '+' + term) * len(phone_fields)
|
||||
)
|
||||
else:
|
||||
where_str = ' OR '.join(
|
||||
f"REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') ILIKE %s"
|
||||
for phone_field in phone_fields
|
||||
)
|
||||
query = f"""
|
||||
SELECT model.id
|
||||
FROM {self._table} model
|
||||
WHERE
|
||||
REGEXP_REPLACE(model.phone, %s, '', 'g') ILIKE %s OR
|
||||
REGEXP_REPLACE(model.mobile, %s, '', 'g') ILIKE %s;
|
||||
WHERE {where_str};
|
||||
"""
|
||||
term = '%' + re.sub(pattern, '', value) + '%'
|
||||
self._cr.execute(query, (
|
||||
pattern, term,
|
||||
pattern, term
|
||||
))
|
||||
self._cr.execute(query, (pattern, term) * len(phone_fields))
|
||||
res = self._cr.fetchall()
|
||||
if not res:
|
||||
return [(0, '=', 1)]
|
||||
|
||||
@@ -45,3 +45,49 @@ class TestSMSActionsCommon(TestSMSCommon, TestSMSRecipients):
|
||||
self.test_phone_records.mapped('phone_nbr'),
|
||||
[False] * 5 + ['+32475110505', '0032475110606', '0032475110707', False]
|
||||
)
|
||||
|
||||
@users('employee')
|
||||
def test_search_phone_mobile_search_equal(self):
|
||||
""" Test searching by phone/mobile with direct search """
|
||||
test_phone_records = self.test_phone_records.with_env(self.env)
|
||||
|
||||
# test "=" search
|
||||
# Currently not suported, returning results for "ilike"
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', '=', '0475')])
|
||||
self.assertEqual(results, test_phone_records[:5])
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', '=', '0475000000')])
|
||||
self.assertEqual(results, test_phone_records[0])
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', '=', '0032475110606')])
|
||||
self.assertEqual(results, test_phone_records[6])
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', '=', '+32475110606')])
|
||||
self.assertEqual(results, test_phone_records[6])
|
||||
|
||||
@users('employee')
|
||||
def test_search_phone_mobile_search_ilike(self):
|
||||
""" Test searching by phone/mobile on various ilike combinations """
|
||||
test_phone_records = self.test_phone_records.with_env(self.env)
|
||||
|
||||
# test ilike search
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'ilike', '0475')])
|
||||
self.assertEqual(results, test_phone_records[:5])
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'ilike', '101')])
|
||||
self.assertEqual(results, test_phone_records[1])
|
||||
|
||||
# test search using +32/0032
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'ilike', '+32475')])
|
||||
self.assertEqual(results, test_phone_records[5:8],
|
||||
'Search on phone_mobile_search: +32/0032 likeliness')
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'ilike', '0032475')])
|
||||
self.assertEqual(results, test_phone_records[5:8],
|
||||
'Search on phone_mobile_search: +32/0032 likeliness')
|
||||
|
||||
# test inverse ilike search
|
||||
# Currently not supported, returning results for "ilike"
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'not ilike', '0475')])
|
||||
# self.assertEqual(results, test_phone_records - test_phone_records[:5],
|
||||
self.assertEqual(results, test_phone_records[:5],
|
||||
'Seach on phone_mobile_search: not ilike not supported')
|
||||
results = self.env['mail.test.sms.bl'].search([('phone_mobile_search', 'not ilike', '101')])
|
||||
# self.assertEqual(results, test_phone_records - test_phone_records[1],
|
||||
self.assertEqual(results, test_phone_records[1],
|
||||
'Seach on phone_mobile_search: not ilike not supported')
|
||||
|
||||
Reference in New Issue
Block a user