diff --git a/backend/clubs/models.py b/backend/clubs/models.py index a26531e6c..8955f7fda 100644 --- a/backend/clubs/models.py +++ b/backend/clubs/models.py @@ -1729,6 +1729,9 @@ class ApplicationSubmission(models.Model): def __str__(self): return f"{self.user.first_name}: {self.application.name}" + class Meta: + unique_together = (("user", "application", "committee"),) + class ApplicationQuestionResponse(models.Model): """ @@ -1757,6 +1760,9 @@ class ApplicationQuestionResponse(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + class Meta: + unique_together = (("question", "submission"),) + class QuestionResponse(models.Model): """ diff --git a/backend/clubs/views.py b/backend/clubs/views.py index 19530ec47..bbb6bcae6 100644 --- a/backend/clubs/views.py +++ b/backend/clubs/views.py @@ -38,7 +38,6 @@ TextField, Value, ) -from django.db.models.expressions import RawSQL from django.db.models.functions import SHA1, Concat, Lower, Trunc from django.db.models.query import prefetch_related_objects from django.http import HttpResponse @@ -4484,8 +4483,11 @@ def question_response(self, *args, **kwargs): submissions page""", } ) - submission = ApplicationSubmission.objects.create( - user=self.request.user, application=application, committee=committee, + submission, _ = ApplicationSubmission.objects.get_or_create( + user=self.request.user, + application=application, + committee=committee, + archived=False, ) key = f"applicationsubmissions:{application.id}" @@ -4509,9 +4511,11 @@ def question_response(self, *args, **kwargs): ): text = question_data.get("text", None) if text is not None and text != "": - obj = ApplicationQuestionResponse.objects.create( - text=text, question=question, submission=submission, - ).save() + obj, _ = ApplicationQuestionResponse.objects.update_or_create( + question=question, + submission=submission, + defaults={"text": text}, + ) response = Response(ApplicationQuestionResponseSerializer(obj).data) elif question_type == ApplicationQuestion.MULTIPLE_CHOICE: multiple_choice_value = question_data.get("multipleChoice", None) @@ -4519,13 +4523,12 @@ def question_response(self, *args, **kwargs): multiple_choice_obj = ApplicationMultipleChoice.objects.filter( question=question, value=multiple_choice_value ).first() - obj = ApplicationQuestionResponse.objects.create( - multiple_choice=multiple_choice_obj, + obj, _ = ApplicationQuestionResponse.objects.update_or_create( question=question, submission=submission, - ).save() + defaults={"multiple_choice": multiple_choice_obj}, + ) response = Response(ApplicationQuestionResponseSerializer(obj).data) - submission.save() return response @action(detail=False, methods=["get"]) @@ -4593,10 +4596,10 @@ def questions(self, *args, **kwargs): response = ( ApplicationQuestionResponse.objects.filter( - submission__user=self.request.user, submission__archived=False + question=question, + submission__user=self.request.user, + submission__archived=False, ) - .filter(question__prompt=question.prompt) - .order_by("-updated_at") .select_related("submission", "multiple_choice", "question") .prefetch_related("question__committees", "question__multiple_choice") .first() @@ -4708,21 +4711,7 @@ def send_emails(self, *args, **kwargs): # Query for recent submissions with user and committee joined submissions = ApplicationSubmission.objects.filter( - application=app, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), - archived=False, + application=app, archived=False, ).select_related("user", "committee") dry_run = self.request.data.get("dry_run") @@ -4931,21 +4920,7 @@ def get_operation_id(self, **kwargs): def get_queryset(self): return ( ApplicationSubmission.objects.filter( - application__is_wharton_council=True, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), - archived=False, + application__is_wharton_council=True, archived=False, ) .annotate( annotated_name=F("application__name"), @@ -4986,30 +4961,9 @@ class ApplicationSubmissionViewSet(viewsets.ModelViewSet): http_method_names = ["get", "post"] def get_queryset(self): - # Use a raw SQL query to obtain the most recent (user, committee) pairs - # of application submissions for a specific application. - # Done by grouping by (user_id, commitee_id) and returning the most - # recent instance in each group, then selecting those instances - app_id = self.kwargs["application_pk"] submissions = ( - ApplicationSubmission.objects.filter( - application=app_id, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), - archived=False, - ) + ApplicationSubmission.objects.filter(application=app_id, archived=False,) .select_related("user__profile", "committee", "application__club") .prefetch_related( Prefetch( @@ -5074,23 +5028,7 @@ def export(self, *args, **kwargs): """ app_id = int(self.kwargs["application_pk"]) data = ( - ApplicationSubmission.objects.filter( - application=app_id, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), - archived=False, - ) + ApplicationSubmission.objects.filter(application=app_id, archived=False,) .select_related("user__profile", "committee", "application__club") .prefetch_related( Prefetch( @@ -5135,19 +5073,6 @@ def exportall(self, *args, **kwargs): ApplicationSubmission.objects.filter( application__is_wharton_council=True, application__application_cycle=cycle, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), archived=False, ) .select_related("application", "application__application_cycle") @@ -5302,21 +5227,7 @@ class ApplicationSubmissionUserViewSet(viewsets.ModelViewSet): def get_queryset(self): submissions = ( ApplicationSubmission.objects.filter( - user=self.request.user, - created_at__in=RawSQL( - """SELECT recent_time - FROM - (SELECT user_id, - committee_id, - application_id, - max(created_at) recent_time - FROM clubs_applicationsubmission - WHERE NOT archived - GROUP BY user_id, - committee_id, application_id) recent_subs""", - (), - ), - archived=False, + user=self.request.user, archived=False, ) .select_related("user__profile", "committee", "application__club") .prefetch_related(