[IMP] phone_validation: improve mobile/phone search
PURPOSE This commit aims to simplify the phone filter of the lead search view to better manage phone numbers containing letters. SPECS The current phone filter will remove all non-digit characters from the input string. When the user enters an american phone number containing letters, the filter can sometimes return phone numbers that do not match exactly with the provided input string. eg: If the user types "hello123" in the search bar, the filter will return all phone numbers matching with "%123%". This pattern will indeed match with "hello123" but it will also match with many other phone numbers containing only "123". To fix the issue, the phone filter will no longer trim all non-digit characters from the input string. The filter will be more standard and will better manage phone numbers containing letters. LINKS Task ID-2424185 COM PR odoo/odoo#64078 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
committed by
Thibault Delavallée
parent
4b8c55697c
commit
0bc56aa7a2
@@ -452,13 +452,13 @@ class TestCRMLead(TestCrmCommon):
|
||||
with self.assertRaises(UserError):
|
||||
self.env['crm.lead'].search([('phone_mobile_search', 'like', '42')])
|
||||
|
||||
# + / 00 prefixes do not block search -> currently not working
|
||||
# self.assertEqual(lead_1 + lead_2, self.env['crm.lead'].search([
|
||||
# ('phone_mobile_search', 'like', '+32499332211')
|
||||
# ]))
|
||||
# self.assertEqual(lead_1 + lead_2, self.env['crm.lead'].search([
|
||||
# ('phone_mobile_search', 'like', '0032499332211')
|
||||
# ]))
|
||||
# + / 00 prefixes do not block search
|
||||
self.assertEqual(lead_1 + lead_2, self.env['crm.lead'].search([
|
||||
('phone_mobile_search', 'like', '+32499332211')
|
||||
]))
|
||||
self.assertEqual(lead_1 + lead_2, self.env['crm.lead'].search([
|
||||
('phone_mobile_search', 'like', '0032499332211')
|
||||
]))
|
||||
self.assertEqual(lead_1 + lead_2, self.env['crm.lead'].search([
|
||||
('phone_mobile_search', 'like', '499332211')
|
||||
]))
|
||||
@@ -466,22 +466,22 @@ class TestCRMLead(TestCrmCommon):
|
||||
('phone_mobile_search', 'like', '3322')
|
||||
]))
|
||||
|
||||
# textual input still possible -> currently not working
|
||||
# self.assertEqual(
|
||||
# self.env['crm.lead'].search([('phone_mobile_search', 'like', 'hello')]),
|
||||
# lead_3,
|
||||
# 'Should behave like a text field'
|
||||
# )
|
||||
# self.assertEqual(
|
||||
# self.env['crm.lead'].search([('phone_mobile_search', 'like', 'Hello')]),
|
||||
# lead_3,
|
||||
# 'Should behave like a text field'
|
||||
# )
|
||||
# self.assertEqual(
|
||||
# self.env['crm.lead'].search([('phone_mobile_search', 'like', 'hello123')]),
|
||||
# self.env['crm.lead'],
|
||||
# 'Should behave like a text field'
|
||||
# )
|
||||
# textual input still possible
|
||||
self.assertEqual(
|
||||
self.env['crm.lead'].search([('phone_mobile_search', 'like', 'hello')]),
|
||||
lead_3,
|
||||
'Should behave like a text field'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.env['crm.lead'].search([('phone_mobile_search', 'like', 'Hello')]),
|
||||
lead_3,
|
||||
'Should behave like a text field'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.env['crm.lead'].search([('phone_mobile_search', 'like', 'hello123')]),
|
||||
self.env['crm.lead'],
|
||||
'Should behave like a text field'
|
||||
)
|
||||
|
||||
@users('user_sales_manager')
|
||||
def test_phone_mobile_search_format(self):
|
||||
@@ -490,7 +490,7 @@ class TestCRMLead(TestCrmCommon):
|
||||
'0499223311',
|
||||
# separators
|
||||
'0499/223311', '0499/22.33.11', '0499/22 33 11', '0499/223 311',
|
||||
# international format
|
||||
# international format -> currently not working
|
||||
# '+32499223311', '0032499223311',
|
||||
]
|
||||
leads = self.env['crm.lead'].create([
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import re
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.phone_validation.tools import phone_validation
|
||||
from odoo.exceptions import AccessError, UserError
|
||||
@@ -45,26 +47,46 @@ 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):
|
||||
value = value.strip()
|
||||
if len(value) < 3:
|
||||
raise UserError(_('Please enter at least 3 characters when searching a Phone/Mobile number.'))
|
||||
|
||||
if len(value) <= 2:
|
||||
raise UserError(_('Please enter at least 3 digits when searching on phone / mobile.'))
|
||||
|
||||
query = f"""
|
||||
pattern = r'[\s\\./\(\)\-]'
|
||||
if value.startswith('+') or value.startswith('00'):
|
||||
# searching on +32485112233 should also finds 0032485112233 (and vice versa)
|
||||
query = f"""
|
||||
SELECT model.id
|
||||
FROM {self._table} model
|
||||
WHERE REGEXP_REPLACE(model.phone, '[^\d+]+', '', 'g') SIMILAR TO CONCAT(%s, REGEXP_REPLACE(%s, '\D+', '', 'g'), '%%')
|
||||
OR REGEXP_REPLACE(model.mobile, '[^\d+]+', '', 'g') SIMILAR TO CONCAT(%s, REGEXP_REPLACE(%s, '\D+', '', 'g'), '%%')
|
||||
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
|
||||
);
|
||||
"""
|
||||
|
||||
# searching on +32485112233 should also finds 00485112233 (00 / + prefix are both valid)
|
||||
# we therefore remove it from input value and search for both of them in db
|
||||
if value.startswith('+') or value.startswith('00'):
|
||||
value = value.replace('+', '').replace('00', '', 1)
|
||||
starts_with = '00|\+'
|
||||
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
|
||||
))
|
||||
else:
|
||||
starts_with = '%'
|
||||
|
||||
self._cr.execute(query, (starts_with, value, starts_with, value))
|
||||
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;
|
||||
"""
|
||||
term = '%' + re.sub(pattern, '', value) + '%'
|
||||
self._cr.execute(query, (
|
||||
pattern, term,
|
||||
pattern, term
|
||||
))
|
||||
res = self._cr.fetchall()
|
||||
if not res:
|
||||
return [(0, '=', 1)]
|
||||
|
||||
Reference in New Issue
Block a user