Skip to content
Snippets Groups Projects
Commit 89b0ac62 authored by Tore.Brede's avatar Tore.Brede
Browse files

GREG-161: Working on search

parent 4945987b
No related branches found
No related tags found
1 merge request!228GREG-161: Search birthdate and name
......@@ -71,13 +71,3 @@ class SpecialPersonSerializer(serializers.ModelSerializer):
"verified",
"roles",
]
class PersonSearchSerializer(serializers.ModelSerializer):
pid = CharField(source="person.id")
first = CharField(source="person.first_name")
last = CharField(source="person.last_name")
class Meta:
model = Identity
fields = ["pid", "first", "last", "value", "type"]
from django.db.models import Q
from rest_framework import mixins
from rest_framework import status
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from greg.api.serializers.person import PersonSearchSerializer, SpecialPersonSerializer
from rest_framework.response import Response
from rest_framework import status
from greg.api.serializers.person import SpecialPersonSerializer
from greg.models import Identity, Person
from greg.permissions import IsSponsor
from gregui import validation
......@@ -14,7 +15,6 @@ from gregui.models import GregUserProfile
class PersonViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericViewSet):
"""
Fetch person info for any guest as long as you are a sponsor
......@@ -39,34 +39,66 @@ class PersonViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericV
return super().perform_update(serializer)
class PersonSearchViewSet(mixins.ListModelMixin, GenericViewSet):
class PersonSearchViewSet(GenericViewSet):
"""Search for persons using email or phone number"""
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated, IsSponsor]
serializer_class = PersonSearchSerializer
def get_queryset(self):
def list(self, request, *args, **kwargs):
if "q" not in self.request.query_params:
return Response(status=status.HTTP_400_BAD_REQUEST)
return Response(
status=status.HTTP_400_BAD_REQUEST,
data={
"code": "no_search_term",
"message": "No search query parameter given",
},
)
if len(self.request.query_params["q"]) > 50:
return Response(status=status.HTTP_400_BAD_REQUEST,
data={
"code": "search_term_too_large",
"message": "Search term is too large",
},
)
hits = self.get_hits()
return Response(hits)
def get_hits(self):
search = self.request.query_params["q"]
# TODO Implement search
split_search = search.split()
words_joined = '|'.join(map(str, split_search))
search_regex = r'^(%s)' % words_joined
hits = []
persons = Person.objects.filter(Q(first_name__iregex=search_regex) |
Q(last_name__iregex=search_regex) |
Q(date_of_birth__iregex=search_regex))[:10]
name_matches = Person.objects.filter(first_name__icontains=search,
last_name__icontains=search)
included_persons = []
for person in persons:
hits.append({"pid": person.id, "first": person.first_name, "last": person.last_name})
included_persons.append(person.id)
return Identity.objects.filter(
value__icontains=search, # icontains to include wrong case emails
identities = Identity.objects.filter(
value__iregex=search_regex,
type__in=[
Identity.IdentityType.PRIVATE_EMAIL,
Identity.IdentityType.PRIVATE_MOBILE_NUMBER,
],
)[:10]
for identity in identities:
if identity.person_id in included_persons:
continue
hits.append({"pid": identity.person_id, "first": identity.person.first_name, "last": identity.person.last_name, "value": identity.value, "type": identity.type})
return hits
class GuestInfoViewSet(mixins.ListModelMixin, GenericViewSet):
"""
......@@ -94,6 +126,6 @@ class GuestInfoViewSet(mixins.ListModelMixin, GenericViewSet):
units = user.sponsor.get_allowed_units()
return (
Person.objects.filter(roles__orgunit__in=list(units))
.distinct()
.order_by("id")
.distinct()
.order_by("id")
)
......@@ -11,9 +11,54 @@ def test_name_search(client, log_in, user_sponsor, create_person):
email="foo@bar.com",
)
url = reverse("gregui-v1:person-search", kwargs={"searchstring": "foo bar"})
url = reverse("gregui-v1:person-search")
log_in(user_sponsor)
response = client.get(url)
# No q-parameter was specified, so the request should return a 400 response
assert response.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_date_of_birth_search(client, log_in, user_sponsor, create_person):
person = create_person(
first_name="foo",
last_name="bar",
email="foo@bar.com",
date_of_birth="2005-06-20"
)
url = reverse("gregui-v1:person-search") + "?q=2005-06-20"
log_in(user_sponsor)
response = client.get(url)
assert len(response.data) == 1
person_ids = list(map(lambda x: x["pid"], response.data))
assert person.id in person_ids
assert response.status_code == status.HTTP_200_OK
@pytest.mark.django_db
def test_multiple_words_search(client, log_in, user_sponsor, create_person):
person = create_person(
first_name="foo",
last_name="bar",
email="foo@bar.com",
date_of_birth="2005-06-20"
)
url = reverse("gregui-v1:person-search") + "?q=foo%20bar"
log_in(user_sponsor)
response = client.get(url)
assert len(response.data) == 1
person_ids = list(map(lambda x: x["pid"], response.data))
assert person.id in person_ids
assert response.status_code == status.HTTP_200_OK
......@@ -326,7 +326,7 @@ def invitation_link_expired(
@pytest.fixture
def create_person() -> Callable[[str, str, str, Optional[str], Optional[str]], Person]:
def create_person() -> Callable[[str, str, str, Optional[str], Optional[str], Optional[datetime.date]], Person]:
# TODO fix the typing...
def create_person(
first_name: str,
......@@ -334,10 +334,12 @@ def create_person() -> Callable[[str, str, str, Optional[str], Optional[str]], P
email: str = None,
nin: str = None,
feide_id: str = None,
date_of_birth: datetime.date = None
) -> Person:
person = Person.objects.create(
first_name=first_name,
last_name=last_name,
date_of_birth=date_of_birth
)
if nin:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment