Skip to content
Snippets Groups Projects
Commit 3bb6609c authored by pka065's avatar pka065
Browse files

Change search principle, make an external search method + add birth date to Person GUI

parent 556899bf
No related branches found
No related tags found
1 merge request!348GREG-292: search for person via v1-api
Pipeline #159722 failed
...@@ -17,7 +17,7 @@ from greg.api.views.sponsor import ( ...@@ -17,7 +17,7 @@ from greg.api.views.sponsor import (
SponsorGuestsViewSet, SponsorGuestsViewSet,
SponsorOrgunitLinkView, SponsorOrgunitLinkView,
) )
from gregui.api.views.person import PersonSearchViewSet from greg.api.views.person import PersonSearchSet
router = DefaultRouter(trailing_slash=False) router = DefaultRouter(trailing_slash=False)
router.register(r"persons", PersonViewSet, basename="person") router.register(r"persons", PersonViewSet, basename="person")
...@@ -76,8 +76,8 @@ urlpatterns += [ ...@@ -76,8 +76,8 @@ urlpatterns += [
name="sponsor_orgunit-detail", name="sponsor_orgunit-detail",
), ),
re_path( re_path(
"person_search/", "person-search/",
PersonSearchViewSet.as_view({"get": "list"}), PersonSearchSet.as_view({"get": "list"}),
name="person-search", name="person-search",
), ),
] ]
...@@ -19,6 +19,7 @@ from greg.api.serializers.person import ( ...@@ -19,6 +19,7 @@ from greg.api.serializers.person import (
) )
from greg.api.serializers.role import RoleSerializer, RoleWriteSerializer from greg.api.serializers.role import RoleSerializer, RoleWriteSerializer
from greg.models import Person, Role, Identity, Consent, ConsentChoice, ConsentType from greg.models import Person, Role, Identity, Consent, ConsentChoice, ConsentType
from search_tools.person_search import person_by_string_query
class PersonViewSet(viewsets.ModelViewSet): class PersonViewSet(viewsets.ModelViewSet):
...@@ -58,6 +59,37 @@ class PersonViewSet(viewsets.ModelViewSet): ...@@ -58,6 +59,37 @@ class PersonViewSet(viewsets.ModelViewSet):
return super().list(request, *args, **kwargs) return super().list(request, *args, **kwargs)
class PersonSearchSet(viewsets.ModelViewSet):
"""Search for persons using name, email, phone number and birth date"""
permission_classes = (permissions.IsAdminUser,)
def list(self, request, *args, **kwargs):
if "q" not in self.request.query_params:
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):
return person_by_string_query(self.request)
class RoleViewSet(viewsets.ModelViewSet): class RoleViewSet(viewsets.ModelViewSet):
"""Person role API""" """Person role API"""
......
from django.db.models import Q
from rest_framework import mixins from rest_framework import mixins
from rest_framework import status from rest_framework import status
from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.authentication import SessionAuthentication, BasicAuthentication
...@@ -16,6 +15,7 @@ from gregui.api.serializers.guest import ( ...@@ -16,6 +15,7 @@ from gregui.api.serializers.guest import (
) )
from gregui.api.serializers.identity import IdentityDuplicateError from gregui.api.serializers.identity import IdentityDuplicateError
from gregui.models import GregUserProfile from gregui.models import GregUserProfile
from search_tools.person_search import person_by_string_query
class PersonViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericViewSet): class PersonViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, GenericViewSet):
...@@ -106,65 +106,7 @@ class PersonSearchViewSet(GenericViewSet): ...@@ -106,65 +106,7 @@ class PersonSearchViewSet(GenericViewSet):
return Response(hits) return Response(hits)
def get_hits(self): def get_hits(self):
search = self.request.query_params["q"] return person_by_string_query(self.request)
include_birth_date = False
if not "gregui" in self.request.version:
include_birth_date = True
split_search = search.split()
words_joined = "|".join(map(str, split_search))
# Create a regex with the terms in the search or-ed together. This will trigger a match
# if one of the fields that are being searched contains one of the terms
search_regex = r"^(%s)" % words_joined
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)
| Q(date_of_birth__iregex=search_regex)
)[:10]
included_persons = []
for person in persons:
output_data = {
"pid": person.id,
"first": person.first_name,
"last": person.last_name,
}
if include_birth_date:
output_data["date_of_birth"] = person.date_of_birth
hits.append(output_data)
included_persons.append(person.id)
if len(hits) == 10:
# Max number of hits, no need to search more
return hits
# Look for hits in e-mail and mobile phone
identities = Identity.objects.filter(
value__iregex=search_regex,
type__in=[
Identity.IdentityType.PRIVATE_EMAIL,
Identity.IdentityType.PRIVATE_MOBILE_NUMBER,
],
)[: (10 - len(hits))]
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): class GuestInfoViewSet(mixins.ListModelMixin, GenericViewSet):
......
from django.db.models import Q
from greg.models import Identity, Person
def person_by_string_query(request):
search = request.query_params["q"]
split_search = search.split()
words_joined = "|".join(map(str, split_search))
# Create a regex with the terms in the search or-ed together. This will trigger a match
# if one of the fields that are being searched contains one of the terms
search_regex = r"^(%s)" % words_joined
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)
| Q(date_of_birth__iregex=search_regex)
)[:10]
included_persons = []
for person in persons:
hits.append(
{
"pid": person.id,
"first": person.first_name,
"last": person.last_name,
"date_of_birth": person.date_of_birth,
}
)
included_persons.append(person.id)
if len(hits) == 10:
# Max number of hits, no need to search more
return hits
# Look for hits in e-mail and mobile phone
identities = Identity.objects.filter(
value__iregex=search_regex,
type__in=[
Identity.IdentityType.PRIVATE_EMAIL,
Identity.IdentityType.PRIVATE_MOBILE_NUMBER,
],
)[: (10 - len(hits))]
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
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