diff --git a/src/pretix/base/models/checkin.py b/src/pretix/base/models/checkin.py index 3f0f3bea7..454564975 100644 --- a/src/pretix/base/models/checkin.py +++ b/src/pretix/base/models/checkin.py @@ -141,7 +141,7 @@ class CheckinList(LoggedModel): return self.positions_query(ignore_status=False) @scopes_disabled() - def positions_inside_query(self, ignore_status=False, at_time=None): + def _filter_positions_inside(self, qs, at_time=None): if at_time is None: c_q = [] else: @@ -149,7 +149,7 @@ class CheckinList(LoggedModel): if "postgresql" not in settings.DATABASES["default"]["ENGINE"]: # Use a simple approach that works on all databases - qs = self.positions_query(ignore_status=ignore_status).annotate( + qs = qs.annotate( last_entry=Subquery( Checkin.objects.filter( *c_q, @@ -202,7 +202,7 @@ class CheckinList(LoggedModel): .values("position_id", "type", "datetime", "cnt_exists_after") .query.sql_with_params() ) - return self.positions_query(ignore_status=ignore_status).filter( + return qs.filter( pk__in=RawSQL( f""" SELECT "position_id" @@ -214,6 +214,10 @@ class CheckinList(LoggedModel): ) ) + @scopes_disabled() + def positions_inside_query(self, ignore_status=False, at_time=None): + return self._filter_positions_inside(self.positions_query(ignore_status=ignore_status), at_time=at_time) + @property def positions_inside(self): return self.positions_inside_query(None) diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py index f3c5ce258..a468c0e1a 100644 --- a/src/pretix/control/forms/filter.py +++ b/src/pretix/control/forms/filter.py @@ -1967,7 +1967,7 @@ class CheckinListAttendeeFilterForm(FilterForm): if s == '1': qs = qs.filter(last_entry__isnull=False) elif s == '2': - qs = qs.filter(pk__in=self.list.positions_inside.values_list('pk')) + qs = self.list._filter_positions_inside(qs) elif s == '3': qs = qs.filter(last_entry__isnull=False).filter( Q(last_exit__isnull=False) & Q(last_exit__gte=F('last_entry')) diff --git a/src/tests/control/test_checkins.py b/src/tests/control/test_checkins.py index d58aa910e..15c803eff 100644 --- a/src/tests/control/test_checkins.py +++ b/src/tests/control/test_checkins.py @@ -228,6 +228,7 @@ def checkin_list_env(): # checkin Checkin.objects.create(position=op_a1_ticket, datetime=now() + timedelta(minutes=1), list=cl) Checkin.objects.create(position=op_a3_ticket, list=cl) + Checkin.objects.create(position=op_a3_ticket, list=cl, type="exit") return event, user, orga, [item_ticket, item_mascot], [order_pending, order_a1, order_a2, order_a3], \ [op_pending_ticket, op_a1_ticket, op_a1_mascot, op_a2_ticket, op_a3_ticket], cl @@ -260,8 +261,10 @@ def test_checkins_list_ordering(client, checkin_list_env, order_key, expected): @pytest.mark.django_db @pytest.mark.parametrize("query, expected", [ ('status=&item=&user=', ['A1Ticket', 'A1Mascot', 'A2Ticket', 'A3Ticket']), - ('status=1&item=&user=', ['A1Ticket', 'A3Ticket']), ('status=0&item=&user=', ['A1Mascot', 'A2Ticket']), + ('status=1&item=&user=', ['A1Ticket', 'A3Ticket']), + ('status=2&item=&user=', ['A1Ticket']), + ('status=3&item=&user=', ['A3Ticket']), ('status=&item=&user=a3dummy', ['A3Ticket']), # match order email ('status=&item=&user=a3dummy', ['A3Ticket']), # match order email, ('status=&item=&user=a4', ['A3Ticket']), # match attendee name