From 74230e79edcc01a17f1ce11c3c5a38d8e2d9a693 Mon Sep 17 00:00:00 2001 From: Struan Donald Date: Wed, 18 Dec 2024 15:56:41 +0000 Subject: [PATCH] add config option to allow skipping questions on right of reply This is initially for WhoFundsThem so MPs only need to response to things where they have an entry in the register. If "right_of_reply_responses_to_ignore" is set as a session config then any response that matches the list, plus blank responses, will not be displayed on the right of reply question screen. The config should be a JSON array with the text descriptions. For multi option values it will skip only if all selected values are in the list. Also updates the section page questions counts to reflect this --- crowdsourcer/models.py | 1 + .../tests/test_right_of_reply_views.py | 27 ++++++++++ crowdsourcer/views/rightofreply.py | 49 +++++++++++++++++-- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/crowdsourcer/models.py b/crowdsourcer/models.py index a6a35a9..9761590 100644 --- a/crowdsourcer/models.py +++ b/crowdsourcer/models.py @@ -261,6 +261,7 @@ def response_counts( ).annotate( num_questions=Subquery( Question.objects.filter( + id__in=questions, questiongroup=OuterRef("questiongroup"), section__title=section, section__marking_session=marking_session, diff --git a/crowdsourcer/tests/test_right_of_reply_views.py b/crowdsourcer/tests/test_right_of_reply_views.py index e44bbbc..f3c54fe 100644 --- a/crowdsourcer/tests/test_right_of_reply_views.py +++ b/crowdsourcer/tests/test_right_of_reply_views.py @@ -12,6 +12,7 @@ PublicAuthority, Response, ResponseType, + SessionConfig, SessionProperties, SessionPropertyValues, ) @@ -400,6 +401,32 @@ def test_questions(self): self.assertRegex(response.content, rb"vehicle fleet") self.assertNotRegex(response.content, rb"Second Session") + def test_ignore_questions_config(self): + url = reverse("authority_ror", args=("Aberdeenshire Council", "Transport")) + response = self.client.get(url) + self.assertEqual(response.status_code, 200) + + self.assertEqual(len(response.context["form"].initial), 2) + self.assertEqual( + response.context["form"].initial[0]["question"].number_and_part, "1" + ) + self.assertEqual( + response.context["form"].initial[1]["question"].number_and_part, "2" + ) + + SessionConfig.objects.create( + name="right_of_reply_responses_to_ignore", + marking_session=MarkingSession.objects.get(label="Default"), + config_type="json", + json_value=["Car share"], + ) + + response = self.client.get(url) + self.assertEqual(len(response.context["form"].initial), 1) + self.assertEqual( + response.context["form"].initial[0]["question"].number_and_part, "1" + ) + def test_questions_alt_session(self): u = User.objects.get(username="other_marker") rt = ResponseType.objects.get(type="Right of Reply") diff --git a/crowdsourcer/views/rightofreply.py b/crowdsourcer/views/rightofreply.py index 77c4255..f9e753d 100644 --- a/crowdsourcer/views/rightofreply.py +++ b/crowdsourcer/views/rightofreply.py @@ -17,6 +17,7 @@ Response, ResponseType, Section, + SessionConfig, SessionProperties, SessionPropertyValues, ) @@ -109,14 +110,31 @@ def get_context_data(self, **kwargs): question_types = ["volunteer", "national_volunteer", "foi"] response_type = ResponseType.objects.get(type="Right of Reply") + authority = PublicAuthority.objects.get(name=context["authority_name"]) + for section in sections: - questions = Question.objects.filter( - section=section, - how_marked__in=question_types, + responses_to_ignore = SessionConfig.get_config( + self.request.current_session, "right_of_reply_responses_to_ignore" ) - question_list = list(questions.values_list("id", flat=True)) + if responses_to_ignore: + questions = ( + Response.objects.filter( + authority=authority, + question__section=section, + question__how_marked__in=question_types, + response_type=ResponseType.objects.get(type="First Mark"), + ) + .exclude(option__description__in=responses_to_ignore) + .exclude(multi_option__description__in=responses_to_ignore) + ) + question_list = list(questions.values_list("question_id", flat=True)) + else: + questions = Question.objects.filter( + section=section, + how_marked__in=question_types, + ) + question_list = list(questions.values_list("id", flat=True)) - authority = PublicAuthority.objects.get(name=context["authority_name"]) args = [ question_list, section.title, @@ -177,6 +195,27 @@ def get_initial_obj(self): initial[r.question.id] = data + responses_to_ignore = SessionConfig.get_config( + self.request.current_session, "right_of_reply_responses_to_ignore" + ) + if responses_to_ignore: + valid_questions = ( + Response.objects.filter( + authority=self.authority, + question__in=self.questions, + response_type=rt, + ) + .exclude(option__description__in=responses_to_ignore) + .exclude(multi_option__description__in=responses_to_ignore) + .values_list("question_id", flat=True) + ) + + new_initial = {} + for k in initial.keys(): + if k in valid_questions: + new_initial[k] = initial[k] + initial = new_initial + if self.has_previous(): ror_rt = ResponseType.objects.get(type="Right of Reply") initial = self.add_previous(initial, ror_rt)