From 74b07be446b49cc86dd8dcb2265e7cbe0827bca4 Mon Sep 17 00:00:00 2001 From: Lasse Fredheim <lass@uio.no> Date: Mon, 23 Jan 2023 14:41:18 +0100 Subject: [PATCH] Fix full name search and add birth date to result --- .../src/routes/sponsor/register/frontPage.tsx | 3 +- gregui/tests/api/views/test_search.py | 49 +++++++++++++++---- search_tools/person_search.py | 31 +++++++----- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/frontend/src/routes/sponsor/register/frontPage.tsx b/frontend/src/routes/sponsor/register/frontPage.tsx index 07fde47a..966de24e 100644 --- a/frontend/src/routes/sponsor/register/frontPage.tsx +++ b/frontend/src/routes/sponsor/register/frontPage.tsx @@ -18,6 +18,7 @@ import { fetchJsonOpts } from 'utils' type Guest = { first: string last: string + date_of_birth: string pid: string value: string } @@ -102,7 +103,7 @@ function FrontPage() { component={Link} to={guestTo} > - {guest.first} {guest.last} + {guest.first} {guest.last} {guest.date_of_birth ? `(${guest.date_of_birth})` : ''} <br /> {guest.value} </MenuItem> diff --git a/gregui/tests/api/views/test_search.py b/gregui/tests/api/views/test_search.py index b9826d54..8dc7c1c1 100644 --- a/gregui/tests/api/views/test_search.py +++ b/gregui/tests/api/views/test_search.py @@ -20,6 +20,39 @@ def test_no_search_parameter_fails(client, log_in, user_sponsor, create_person): assert response.status_code == status.HTTP_400_BAD_REQUEST +@pytest.mark.django_db +def test_full_name_search(client, log_in, user_sponsor, create_person): + person1 = create_person( + first_name="Fjong", + last_name="Larsen", + email="fjong@post.no", + phone_number="+4712345678", + ) + person2 = create_person( + first_name="Stiv", + last_name="Hansen", + email="hansen@post.no", + phone_number="+4787654321", + ) + person3 = create_person( + first_name="Larsen", + last_name="Fjong", + email="pjofsen@post.no", + phone_number="+4711111111", + ) + + url = reverse("gregui-v1:person-search") + "?q=fjong%20larsen" + + log_in(user_sponsor) + response = client.get(url) + + person_ids = list(map(lambda x: x["pid"], response.data)) + + assert person1.id in person_ids + assert person2.id not in person_ids + assert person3.id in person_ids + + @pytest.mark.django_db def test_date_of_birth_search(client, log_in, user_sponsor, create_person): person = create_person( @@ -93,24 +126,24 @@ def test_phone_number_search(client, log_in, user_sponsor, create_person): @pytest.mark.django_db def test_multiple_words_search(client, log_in, user_sponsor, create_person): - person = create_person( + create_person( first_name="foo", last_name="bar", email="example@company.com", ) - person2 = create_person( + create_person( first_name="test", last_name="test2", email="foo@bar.com", date_of_birth="2006-06-20", ) - person3 = create_person( + create_person( first_name="Bob", last_name="Smith", email="bob@smith.com", date_of_birth="2005-06-20", ) - person4 = create_person( + create_person( first_name="Frank", last_name="Paulsen", email="frank@paulsen.com", @@ -121,15 +154,11 @@ def test_multiple_words_search(client, log_in, user_sponsor, create_person): log_in(user_sponsor) response = client.get(url) - assert len(response.data) == 3 + assert len(response.data) == 0 person_ids = list(map(lambda x: x["pid"], response.data)) - assert person.id in person_ids - assert person2.id in person_ids - assert person3.id in person_ids - assert person4.id not in person_ids - assert response.status_code == status.HTTP_200_OK + assert not person_ids @pytest.mark.django_db diff --git a/search_tools/person_search.py b/search_tools/person_search.py index c185786b..1a9037b1 100644 --- a/search_tools/person_search.py +++ b/search_tools/person_search.py @@ -1,4 +1,5 @@ -from django.db.models import Q +from django.db.models import Q, Value, CharField +from django.db.models.functions import Concat from greg.models import Identity, Person @@ -9,17 +10,24 @@ def person_by_string_query(request): else: id_field_name = "person_id" - split_search = search.split() - search_regex = "|".join(map(str, split_search)) - + split_search = search.lower().split() + search_regex = "(.*)".join(split_search) + reversed_search_regex = "(.*)".join(list(reversed(split_search))) + print(split_search, search_regex) hits = [] # First look for hits on name and birth date - persons = Person.objects.filter( - Q(first_name__iregex=search_regex) - | Q(last_name__iregex=search_regex) + persons = Person.objects.annotate( + full_name=Concat( + "first_name", Value(" "), "last_name", output_field=CharField() + ) + ).filter( + Q(full_name__iregex=search_regex) + | Q(full_name__iregex=reversed_search_regex) | Q(date_of_birth__iregex=search_regex) - )[:10] - + )[ + :20 + ] + print(persons) included_persons = [] for person in persons: hits.append( @@ -32,7 +40,7 @@ def person_by_string_query(request): ) included_persons.append(person.id) - if len(hits) == 10: + if len(hits) == 20: # Max number of hits, no need to search more return hits @@ -43,7 +51,7 @@ def person_by_string_query(request): Identity.IdentityType.PRIVATE_EMAIL, Identity.IdentityType.PRIVATE_MOBILE_NUMBER, ], - )[: (10 - len(hits))] + )[: (20 - len(hits))] for identity in identities: if identity.person_id in included_persons: @@ -54,6 +62,7 @@ def person_by_string_query(request): id_field_name: identity.person_id, "first": identity.person.first_name, "last": identity.person.last_name, + "date_of_birth": identity.person.date_of_birth, "value": identity.value, "type": identity.type, } -- GitLab