diff --git a/addons/crm/tests/test_crm_lead.py b/addons/crm/tests/test_crm_lead.py index ae0b9b10ccc..f4e32a50d90 100644 --- a/addons/crm/tests/test_crm_lead.py +++ b/addons/crm/tests/test_crm_lead.py @@ -735,10 +735,14 @@ class TestCRMLead(TestCrmCommon): lead_3, 'Should behave like a text field' ) - self.assertEqual( + self.assertFalse( self.env['crm.lead'].search([('phone_mobile_search', 'like', 'Hello')]), + 'Should behave like a text field (case sensitive)' + ) + self.assertEqual( + self.env['crm.lead'].search([('phone_mobile_search', 'ilike', 'Hello')]), lead_3, - 'Should behave like a text field' + 'Should behave like a text field (case insensitive)' ) self.assertEqual( self.env['crm.lead'].search([('phone_mobile_search', 'like', 'hello123')]), diff --git a/addons/phone_validation/models/mail_thread_phone.py b/addons/phone_validation/models/mail_thread_phone.py index 931dee5f565..059eeb399f2 100644 --- a/addons/phone_validation/models/mail_thread_phone.py +++ b/addons/phone_validation/models/mail_thread_phone.py @@ -68,37 +68,52 @@ class PhoneMixin(models.AbstractModel): raise UserError(_('Please enter at least 3 characters when searching a Phone/Mobile number.')) pattern = r'[\s\\./\(\)\-]' + sql_operator = {'=like': 'LIKE', '=ilike': 'ILIKE'}.get(operator, operator) + 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 {where_str}; - """ - term = re.sub(pattern, '', value[1 if value.startswith('+') else 2:]) + '%' + if operator in expression.NEGATIVE_TERM_OPERATORS: + # 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 = ' AND '.join( + f"""model.{phone_field} IS NULL OR ( + REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') {sql_operator} %s OR + REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') {sql_operator} %s + )""" + for phone_field in phone_fields + ) + else: + # 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') {sql_operator} %s OR + REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') {sql_operator} %s + )""" + for phone_field in phone_fields + ) + query = f"SELECT model.id FROM {self._table} model WHERE {where_str};" + + term = re.sub(pattern, '', value[1 if value.startswith('+') else 2:]) + if operator not in ('=', '!='): # for like operators + term = f'{term}%' self._cr.execute( - query, - (pattern, '00' + term, pattern, '+' + term) * len(phone_fields) + 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 {where_str}; - """ - term = '%' + re.sub(pattern, '', value) + '%' + if operator in expression.NEGATIVE_TERM_OPERATORS: + where_str = ' AND '.join( + f"(model.{phone_field} IS NULL OR REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') {sql_operator} %s)" + for phone_field in phone_fields + ) + else: + where_str = ' OR '.join( + f"(model.{phone_field} IS NOT NULL AND REGEXP_REPLACE(model.{phone_field}, %s, '', 'g') {sql_operator} %s)" + for phone_field in phone_fields + ) + query = f"SELECT model.id FROM {self._table} model WHERE {where_str};" + term = re.sub(pattern, '', value) + if operator not in ('=', '!='): # for like operators + term = f'%{term}%' self._cr.execute(query, (pattern, term) * len(phone_fields)) res = self._cr.fetchall() if not res: diff --git a/addons/test_mail_sms/tests/test_mail_thread_phone.py b/addons/test_mail_sms/tests/test_mail_thread_phone.py index cd5350a45de..0ad61f0e279 100644 --- a/addons/test_mail_sms/tests/test_mail_thread_phone.py +++ b/addons/test_mail_sms/tests/test_mail_thread_phone.py @@ -75,9 +75,8 @@ class TestSMSActionsCommon(TestSMSCommon, TestSMSRecipients): 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]) + self.assertFalse(results, 'Search on phone_mobile_search: = should return only matching results') 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')]) @@ -105,12 +104,7 @@ class TestSMSActionsCommon(TestSMSCommon, TestSMSRecipients): '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') + self.assertEqual(results, test_phone_records - test_phone_records[:5]) 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') + self.assertEqual(results, test_phone_records - test_phone_records[1])