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