From 28b7be01cce6455bcbe998c375cbac09fabe18ba Mon Sep 17 00:00:00 2001
From: Jorran de Wit <jorrandewit@outlook.com>
Date: Wed, 19 Dec 2018 08:30:02 +0100
Subject: [PATCH] Add fuzzy search to select-referee form

---
 submissions/forms.py                            |  7 +++++++
 .../migrations/0050_auto_20181219_0825.py       | 17 +++++++++++++++++
 submissions/views.py                            | 12 +++++-------
 3 files changed, 29 insertions(+), 7 deletions(-)
 create mode 100644 submissions/migrations/0050_auto_20181219_0825.py

diff --git a/submissions/forms.py b/submissions/forms.py
index fb79b2722..2b202e062 100644
--- a/submissions/forms.py
+++ b/submissions/forms.py
@@ -7,6 +7,7 @@ import re
 
 from django import forms
 from django.conf import settings
+from django.contrib.postgres.search import TrigramSimilarity
 from django.db import transaction
 from django.db.models import Q
 from django.forms.formsets import ORDERING_FIELD_NAME
@@ -35,6 +36,7 @@ from mails.utils import DirectMailUtil
 from preprints.helpers import generate_new_scipost_identifier
 from preprints.models import Preprint
 from production.utils import get_or_create_production_stream
+from profiles.models import Profile
 from scipost.constants import SCIPOST_SUBJECT_AREAS
 from scipost.services import ArxivCaller
 from scipost.models import Contributor, Remark
@@ -911,6 +913,11 @@ class RefereeSearchForm(forms.Form):
     last_name = forms.CharField(widget=forms.TextInput({
         'placeholder': 'Search for a referee in the SciPost Profiles database'}))
 
+    def search(self):
+        return Profile.objects.annotate(
+            similarity=TrigramSimilarity('last_name', self.cleaned_data['last_name']),
+        ).filter(similarity__gt=0.3).order_by('-similarity')
+
 
 class ConsiderRefereeInvitationForm(forms.Form):
     accept = forms.ChoiceField(widget=forms.RadioSelect, choices=ASSIGNMENT_BOOL,
diff --git a/submissions/migrations/0050_auto_20181219_0825.py b/submissions/migrations/0050_auto_20181219_0825.py
new file mode 100644
index 000000000..9495f00fa
--- /dev/null
+++ b/submissions/migrations/0050_auto_20181219_0825.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-12-19 07:25
+from __future__ import unicode_literals
+
+from django.db import migrations
+from django.contrib.postgres.operations import TrigramExtension
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('submissions', '0049_auto_20181204_2040'),
+    ]
+
+    operations = [
+        TrigramExtension(),
+    ]
diff --git a/submissions/views.py b/submissions/views.py
index 9a2475b3d..612307310 100644
--- a/submissions/views.py
+++ b/submissions/views.py
@@ -917,11 +917,9 @@ def select_referee(request, identifier_w_vn_nr):
                                    preprint__identifier_w_vn_nr=identifier_w_vn_nr)
     context = {}
     queryresults = ''
-    referee_search_form = RefereeSearchForm(request.GET or None)
-    if referee_search_form.is_valid():
-        profiles_found = Profile.objects.filter(
-            last_name__icontains=referee_search_form.cleaned_data['last_name'])
-        context['profiles_found'] = profiles_found
+    form = RefereeSearchForm(request.GET or None)
+    if form.is_valid():
+        context['profiles_found'] = form.search()
         # Check for recent co-authorship (thus referee disqualification)
         try:
             sub_auth_boolean_str = '((' + (submission
@@ -930,7 +928,7 @@ def select_referee(request, identifier_w_vn_nr):
             for author in submission.metadata['entries'][0]['authors'][1:]:
                 sub_auth_boolean_str += '+OR+' + author['name'].split()[-1]
             sub_auth_boolean_str += ')+AND+'
-            search_str = sub_auth_boolean_str + referee_search_form.cleaned_data['last_name'] + ')'
+            search_str = sub_auth_boolean_str + form.cleaned_data['last_name'] + ')'
             queryurl = ('https://export.arxiv.org/api/query?search_query=au:%s'
                         % search_str + '&sortBy=submittedDate&sortOrder=descending'
                         '&max_results=5')
@@ -942,7 +940,7 @@ def select_referee(request, identifier_w_vn_nr):
     context.update({
         'submission': submission,
         'workdays_left_to_report': workdays_between(timezone.now(), submission.reporting_deadline),
-        'referee_search_form': referee_search_form,
+        'referee_search_form': form,
         'queryresults': queryresults,
         'profile_email_form': ProfileEmailForm(initial={'primary': True}),
     })
-- 
GitLab