Добавлена умная фильтрация для поиска по номерам телефонов
Проблема: Поиск "x3m" неправильно находит клиента Наталью потому что её номер
содержит цифру "3". Это происходило, потому что система искала по любым цифрам
в query, даже если это явно не номер телефона.
Решение: Добавлена функция is_query_phone_only() которая проверяет, содержит ли
query ТОЛЬКО телефонные символы (цифры, +, -, (), пробелы, точка).
Поиск по номеру телефона происходит ТОЛЬКО если:
1. Query состоит ТОЛЬКО из телефонных символов (никаких букв)
2. И количество цифр >= 3
Примеры:
- "x3m" → НЕ ищет по цифре "3" (содержит букву)
- "29" → НЕ ищет по цифрам (только 2 цифры, нужно минимум 3)
- "295" → ИЩЕТ по цифрам "295" (только цифры, 3+ символов)
- "+375291234567" → ИЩЕТ по номеру (только телефонные символы)
- "team_x3m" → НЕ ищет по цифрам (содержит буквы и _)
Изменения:
1. Добавлена функция is_query_phone_only() в views.py
2. Обновлена api_search_customers() для использования новой функции
3. Обновлена customer_list() для использования новой функции
4. Добавлены 19 unit-тестов для is_query_phone_only()
Результаты тестирования:
✓ 42 теста всего (23 для determine_search_strategy + 19 для is_query_phone_only)
✓ Все тесты проходят успешно
Критические тест-кейсы:
✓ is_query_phone_only('x3m') == False (решает исходную проблему)
✓ is_query_phone_only('295') == True
✓ is_query_phone_only('+375291234567') == True
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from django.test import TestCase
|
||||
from .views import determine_search_strategy
|
||||
from .views import determine_search_strategy, is_query_phone_only
|
||||
|
||||
|
||||
class DetermineSearchStrategyTestCase(TestCase):
|
||||
@@ -158,3 +158,95 @@ class DetermineSearchStrategyTestCase(TestCase):
|
||||
strategy, search_value = determine_search_strategy('natul')
|
||||
self.assertEqual(strategy, 'universal')
|
||||
self.assertEqual(search_value, 'natul')
|
||||
|
||||
|
||||
class IsQueryPhoneOnlyTestCase(TestCase):
|
||||
"""
|
||||
Тесты для функции is_query_phone_only().
|
||||
|
||||
Проверяют, что функция правильно определяет, содержит ли query
|
||||
только символы номера телефона (цифры, +, -, (), пробелы).
|
||||
"""
|
||||
|
||||
# ===== Должны вернуть True (только телефонные символы) =====
|
||||
def test_phone_only_digits(self):
|
||||
"""Query '295' должен вернуть True (только цифры)"""
|
||||
self.assertTrue(is_query_phone_only('295'))
|
||||
|
||||
def test_phone_only_single_digit(self):
|
||||
"""Query '5' должен вернуть True (одна цифра)"""
|
||||
self.assertTrue(is_query_phone_only('5'))
|
||||
|
||||
def test_phone_with_plus(self):
|
||||
"""Query '+375291234567' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('+375291234567'))
|
||||
|
||||
def test_phone_with_dashes(self):
|
||||
"""Query '029-123-45' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('029-123-45'))
|
||||
|
||||
def test_phone_with_parentheses(self):
|
||||
"""Query '(029) 123-45' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('(029) 123-45'))
|
||||
|
||||
def test_phone_with_spaces(self):
|
||||
"""Query '029 123 45' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('029 123 45'))
|
||||
|
||||
def test_phone_complex_format(self):
|
||||
"""Query '+375 (29) 123-45-67' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('+375 (29) 123-45-67'))
|
||||
|
||||
def test_phone_with_dot(self):
|
||||
"""Query '029.123.45' должен вернуть True"""
|
||||
self.assertTrue(is_query_phone_only('029.123.45'))
|
||||
|
||||
# ===== Должны вернуть False (содержат буквы или другие символы) =====
|
||||
def test_query_with_letters_only(self):
|
||||
"""Query 'abc' должен вернуть False (содержит буквы)"""
|
||||
self.assertFalse(is_query_phone_only('abc'))
|
||||
|
||||
def test_query_with_mixed_letters_digits(self):
|
||||
"""Query 'x3m' должен вернуть False (содержит буквы)"""
|
||||
self.assertFalse(is_query_phone_only('x3m'))
|
||||
|
||||
def test_query_name_with_digits(self):
|
||||
"""Query 'team_x3m' должен вернуть False (содержит буквы и _)"""
|
||||
self.assertFalse(is_query_phone_only('team_x3m'))
|
||||
|
||||
def test_query_name_cyrillic(self):
|
||||
"""Query 'Наталья' должен вернуть False (содержит кириллицу)"""
|
||||
self.assertFalse(is_query_phone_only('Наталья'))
|
||||
|
||||
def test_query_with_underscore(self):
|
||||
"""Query '123_456' должен вернуть False (содержит _)"""
|
||||
self.assertFalse(is_query_phone_only('123_456'))
|
||||
|
||||
def test_query_with_hash(self):
|
||||
"""Query '123#456' должен вернуть False (содержит #)"""
|
||||
self.assertFalse(is_query_phone_only('123#456'))
|
||||
|
||||
def test_empty_string(self):
|
||||
"""Query '' должен вернуть False (пустая строка)"""
|
||||
self.assertFalse(is_query_phone_only(''))
|
||||
|
||||
def test_only_spaces(self):
|
||||
"""Query ' ' должен вернуть True (только пробелы разрешены)"""
|
||||
self.assertTrue(is_query_phone_only(' '))
|
||||
|
||||
# ===== Real-world cases =====
|
||||
def test_real_world_case_x3m_should_not_be_phone(self):
|
||||
"""
|
||||
Real-world case: "x3m" содержит букву, поэтому НЕ похож на телефон.
|
||||
Это критично для решения проблемы с поиском Натальи.
|
||||
"""
|
||||
self.assertFalse(is_query_phone_only('x3m'))
|
||||
# Значит, при поиске "x3m" НЕ будет поиска по цифре "3" в телефонах
|
||||
|
||||
def test_real_world_case_295_should_be_phone(self):
|
||||
"""Real-world case: '295' только цифры, похож на телефон"""
|
||||
self.assertTrue(is_query_phone_only('295'))
|
||||
|
||||
def test_real_world_full_phone_number(self):
|
||||
"""Real-world case: полный номер в стандартном формате"""
|
||||
self.assertTrue(is_query_phone_only('+375 (29) 598-62-62'))
|
||||
|
||||
Reference in New Issue
Block a user