From 86395a5ffa13750fe7f26cd04fd634646922c69c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jean-S=C3=A9bastien=20Caux?= <git@jscaux.org>
Date: Sat, 26 Nov 2022 08:09:39 +0100
Subject: [PATCH] Simplify filtering for latest Submission

---
 scipost_django/ontology/models/branch.py      |  2 +-
 .../templates/ontology/_topic_card.html       |  2 +-
 .../templates/profiles/_profile_card.html     |  2 +-
 .../submissions/api/viewsets/submission.py    |  2 +-
 scipost_django/submissions/forms.py           |  4 +--
 .../submissions/managers/submission.py        | 29 ++++---------------
 scipost_django/submissions/search_indexes.py  |  2 +-
 scipost_django/submissions/views.py           |  2 +-
 8 files changed, 13 insertions(+), 32 deletions(-)

diff --git a/scipost_django/ontology/models/branch.py b/scipost_django/ontology/models/branch.py
index 7f469cfe9..4f12ab415 100644
--- a/scipost_django/ontology/models/branch.py
+++ b/scipost_django/ontology/models/branch.py
@@ -34,4 +34,4 @@ class Branch(models.Model):
 
     @property
     def submissions(self):
-        return Submission.objects.public_newest().filter(acad_field__branch=self.id)
+        return Submission.objects.public_latest().filter(acad_field__branch=self.id)
diff --git a/scipost_django/ontology/templates/ontology/_topic_card.html b/scipost_django/ontology/templates/ontology/_topic_card.html
index 964049117..5ee6772a4 100644
--- a/scipost_django/ontology/templates/ontology/_topic_card.html
+++ b/scipost_django/ontology/templates/ontology/_topic_card.html
@@ -94,7 +94,7 @@
 	  </div>
 	  <div class="card-body">
 	    <ul>
-	      {% for sub in topic.submission_set.public_newest.unpublished %}
+	      {% for sub in topic.submission_set.public_latest.unpublished %}
     		<li>
     		  <a href="{{ sub.get_absolute_url }}">{{ sub.title }}</a>
     		  <br>by {{ sub.author_list }}
diff --git a/scipost_django/profiles/templates/profiles/_profile_card.html b/scipost_django/profiles/templates/profiles/_profile_card.html
index 9eb1ceb52..f631202ab 100644
--- a/scipost_django/profiles/templates/profiles/_profile_card.html
+++ b/scipost_django/profiles/templates/profiles/_profile_card.html
@@ -130,7 +130,7 @@
       </div>
       <div class="card-body">
 	<ul>
-	  {% for sub in profile.contributor.submissions.public_newest.unpublished %}
+	  {% for sub in profile.contributor.submissions.public_latest.unpublished %}
 	    <li><a href="{{ sub.get_absolute_url }}">{{ sub }}</a></li>
 	  {% empty %}
 	    <li>No ongoing Submission found</li>
diff --git a/scipost_django/submissions/api/viewsets/submission.py b/scipost_django/submissions/api/viewsets/submission.py
index 915a8c5e8..b03decaeb 100644
--- a/scipost_django/submissions/api/viewsets/submission.py
+++ b/scipost_django/submissions/api/viewsets/submission.py
@@ -41,7 +41,7 @@ class SubmissionPublicAPIViewSet(
 class SubmissionPublicSearchAPIViewSet(
     FilteringOptionsActionMixin, viewsets.ReadOnlyModelViewSet
 ):
-    queryset = Submission.objects.public_newest().unpublished()
+    queryset = Submission.objects.public_latest().unpublished()
     permission_classes = [
         AllowAny,
     ]
diff --git a/scipost_django/submissions/forms.py b/scipost_django/submissions/forms.py
index 3d30b3edb..0dd9a33dc 100644
--- a/scipost_django/submissions/forms.py
+++ b/scipost_django/submissions/forms.py
@@ -131,7 +131,7 @@ class SubmissionSearchForm(forms.Form):
         """
         Return all Submission objects fitting search criteria.
         """
-        submissions = Submission.objects.public_newest().unpublished()
+        submissions = Submission.objects.public_latest().unpublished()
         if self.acad_field_slug and self.acad_field_slug != "all":
             submissions = submissions.filter(acad_field__slug=self.acad_field_slug)
             if self.specialty_slug and self.specialty_slug != "all":
@@ -496,7 +496,7 @@ class SubmissionOldSearchForm(forms.Form):
 
     def search_results(self):
         """Return all Submission objects according to search."""
-        return Submission.objects.public_newest().filter(
+        return Submission.objects.public_latest().filter(
             title__icontains=self.cleaned_data.get("title", ""),
             author_list__icontains=self.cleaned_data.get("author", ""),
             abstract__icontains=self.cleaned_data.get("abstract", ""),
diff --git a/scipost_django/submissions/managers/submission.py b/scipost_django/submissions/managers/submission.py
index e235a5212..16086616a 100644
--- a/scipost_django/submissions/managers/submission.py
+++ b/scipost_django/submissions/managers/submission.py
@@ -11,25 +11,6 @@ from .. import constants
 
 
 class SubmissionQuerySet(models.QuerySet):
-    def _newest_version_only(self, queryset):
-        """
-        TODO: Make more efficient... with agregation or whatever.
-        TODO: just replace this by the `latest` filter defined below.
-
-        The current Queryset should return only the latest version
-        of the submissions.
-
-        Method only compatible with PostgreSQL
-        """
-        # This method used a double query, which is a consequence of the complex distinct()
-        # filter combined with the PostGresQL engine. Without the double query, ordering
-        # on a specific field after filtering seems impossible.
-        ids = (
-            queryset.order_by("thread_hash", "-submission_date")
-            .distinct("thread_hash")
-            .values_list("id", flat=True)
-        )
-        return queryset.filter(id__in=ids)
 
     def latest(self, queryset):
         return queryset.exclude(status=self.model.RESUBMITTED)
@@ -181,12 +162,12 @@ class SubmissionQuerySet(models.QuerySet):
             status__in=[self.model.RESUBMITTED, self.model.PUBLISHED]
         )
 
-    def public_newest(self):
+    def public_latest(self):
         """
-        This query contains set of public() submissions, filtered to only the newest available
+        This query contains set of public() submissions, filtered to only the latest available
         version.
         """
-        return self._newest_version_only(self.public())
+        return self.latest(self.public())
 
     def treated(self):
         """This query returns all Submissions that are presumed to be 'done'."""
@@ -246,11 +227,11 @@ class SubmissionQuerySet(models.QuerySet):
 
     def rejected(self):
         """Return rejected Submissions."""
-        return self._newest_version_only(self.filter(status=self.model.REJECTED))
+        return self.latest(self.filter(status=self.model.REJECTED))
 
     def withdrawn(self):
         """Return withdrawn Submissions."""
-        return self._newest_version_only(self.filter(status=self.model.WITHDRAWN))
+        return self.latest(self.filter(status=self.model.WITHDRAWN))
 
     def open_for_reporting(self):
         """Return Submissions open for reporting."""
diff --git a/scipost_django/submissions/search_indexes.py b/scipost_django/submissions/search_indexes.py
index 56f906b48..38b5f1fbc 100644
--- a/scipost_django/submissions/search_indexes.py
+++ b/scipost_django/submissions/search_indexes.py
@@ -23,4 +23,4 @@ class SubmissionIndex(indexes.SearchIndex, indexes.Indexable):
 
     def index_queryset(self, using=None):
         """Used when the entire index for model is updated."""
-        return self.get_model().objects.public_newest()
+        return self.get_model().objects.public_latest()
diff --git a/scipost_django/submissions/views.py b/scipost_django/submissions/views.py
index bd604548a..7bb49b9c8 100644
--- a/scipost_django/submissions/views.py
+++ b/scipost_django/submissions/views.py
@@ -551,7 +551,7 @@ class SubmissionListView(PaginationMixin, ListView):
 
     def get_queryset(self):
         """Return queryset, filtered with GET request data if given."""
-        queryset = Submission.objects.public_newest()
+        queryset = Submission.objects.public_latest()
         self.form = self.form(self.request.GET)
         if "field" in self.request.GET:
             queryset = queryset.filter(acad_field__slug=self.request.GET["field"])
-- 
GitLab