From ae8ac3c24f2b476fd2351977e5188e2a2d846d44 Mon Sep 17 00:00:00 2001 From: xAndy Date: Sun, 1 Jun 2025 02:45:21 +0200 Subject: [PATCH] add more bulk message filters, shuffle recipients --- shiftregister/team/forms.py | 51 +++++++++++++++++++++++++++++ shiftregister/team/tests.py | 64 ++++++++++++++++++++++++++++++++++++- shiftregister/team/views.py | 2 +- 3 files changed, 115 insertions(+), 2 deletions(-) diff --git a/shiftregister/team/forms.py b/shiftregister/team/forms.py index b869aa4..179bf89 100644 --- a/shiftregister/team/forms.py +++ b/shiftregister/team/forms.py @@ -62,6 +62,57 @@ HELPER_FILTERS = { reg_count=Count("shiftregistration") ).filter(reg_count=0), }, + "good_helpers": { + "label": "Zuverlässige Helfis (Check-in ohne Fehlzeiten)", + "query": lambda base_query: base_query.annotate( + checked_in_count=Count( + Case( + When( + shiftregistration__state=ShiftRegistration.RegState.CHECKED_IN, + then=1, + ), + output_field=IntegerField(), + ) + ), + failed_count=Count( + Case( + When( + shiftregistration__state=ShiftRegistration.RegState.FAILED, + then=1, + ), + output_field=IntegerField(), + ) + ), + ) + .filter(checked_in_count__gte=1, failed_count=0) + .distinct(), + }, + "good_helpers_no_feedback": { + "label": "Zuverlässige Helfis ohne Feedback", + "query": lambda base_query: base_query.annotate( + checked_in_count=Count( + Case( + When( + shiftregistration__state=ShiftRegistration.RegState.CHECKED_IN, + then=1, + ), + output_field=IntegerField(), + ) + ), + failed_count=Count( + Case( + When( + shiftregistration__state=ShiftRegistration.RegState.FAILED, + then=1, + ), + output_field=IntegerField(), + ) + ), + ) + .filter(checked_in_count__gte=1, failed_count=0) + .exclude(feedback__isnull=False) + .distinct(), + }, } diff --git a/shiftregister/team/tests.py b/shiftregister/team/tests.py index 95c285b..edf72bc 100644 --- a/shiftregister/team/tests.py +++ b/shiftregister/team/tests.py @@ -128,10 +128,64 @@ class BulkMessageFilterTests(TestCase): self.assertIn(self.helper3, helpers) # No shifts self.assertNotIn(self.helper4, helpers) # Not validated + def test_good_helpers_filter(self): + """Test that 'good_helpers' filter returns only helpers with check-ins and no failed shifts""" + # Add a failed shift for helper1 + ShiftRegistration.objects.create( + shift=self.current_shift, + helper=self.helper1, + state=ShiftRegistration.RegState.FAILED, + ) + + base_query = Helper.objects.filter(number_validated=True) + helpers = HELPER_FILTERS["good_helpers"]["query"](base_query) + + self.assertEqual(helpers.count(), 1) + self.assertNotIn(self.helper1, helpers) # Has a failed shift + self.assertIn(self.helper2, helpers) # Has only checked-in shifts + self.assertNotIn(self.helper3, helpers) # Has no shifts + self.assertNotIn(self.helper4, helpers) # Not validated + + def test_good_helpers_no_feedback_filter(self): + """Test that 'good_helpers_no_feedback' filter returns only good helpers without feedback""" + from shiftregister.feedback.models import Feedback + + # Add feedback for helper2 + Feedback.objects.create( + helper=self.helper2, + party=Feedback.PartyState.YES, + next_year=True, + ) + + base_query = Helper.objects.filter(number_validated=True) + helpers = HELPER_FILTERS["good_helpers_no_feedback"]["query"](base_query) + + self.assertEqual(helpers.count(), 1) + self.assertIn(self.helper1, helpers) # Has no feedback + self.assertNotIn(self.helper2, helpers) # Has feedback + self.assertNotIn(self.helper3, helpers) # Has no shifts + self.assertNotIn(self.helper4, helpers) # Not validated + def test_bulk_message_view_with_filters(self): """Test that the bulk message view correctly applies filters""" test_message = "Test message" + # Add a failed shift for helper1 to test good_helpers filter + ShiftRegistration.objects.create( + shift=self.current_shift, + helper=self.helper1, + state=ShiftRegistration.RegState.FAILED, + ) + + # Add feedback for helper2 to test good_helpers_no_feedback filter + from shiftregister.feedback.models import Feedback + + Feedback.objects.create( + helper=self.helper2, + party=Feedback.PartyState.YES, + next_year=True, + ) + for filter_key in HELPER_FILTERS.keys(): response = self.client.post( reverse("team:bulk_message"), @@ -146,9 +200,17 @@ class BulkMessageFilterTests(TestCase): elif filter_key == "checked_in": expected_count = 2 elif filter_key == "current": + expected_count = 2 + elif filter_key == "no_shifts": expected_count = 1 - else: # no_shifts + elif filter_key == "good_helpers": expected_count = 1 + elif filter_key == "good_helpers_no_feedback": + expected_count = ( + 0 # but has left feedback. we cover the filter in another test + ) + else: + self.fail(f"Unexpected filter key: {filter_key}") self.assertEqual( Message.objects.filter(text__startswith=test_message).count(), diff --git a/shiftregister/team/views.py b/shiftregister/team/views.py index 2b8c959..4d42b4d 100644 --- a/shiftregister/team/views.py +++ b/shiftregister/team/views.py @@ -135,7 +135,7 @@ def bulk_message(request): helper_filter = form.cleaned_data["helper_filter"] # Get the query function from HELPER_FILTERS and apply it - helpers = HELPER_FILTERS[helper_filter]["query"](base_query) + helpers = HELPER_FILTERS[helper_filter]["query"](base_query).order_by("?") try: outbox = []