diff --git a/doc/api/resources/orders.rst b/doc/api/resources/orders.rst index 043a51112d..f204e260e3 100644 --- a/doc/api/resources/orders.rst +++ b/doc/api/resources/orders.rst @@ -203,7 +203,8 @@ checkins list of objects List of **succe ├ datetime datetime Time of check-in ├ type string Type of scan (defaults to ``entry``) ├ gate integer Internal ID of the gate. Can be ``null``. -├ device integer Internal ID of the device. Can be ``null``. +├ device integer Internal ID of the device. Can be ``null``. **Deprecated**, since this ID is not otherwise used in the API and is therefore not very useful. +├ device_id integer Attribute ``device_id`` of the device. Can be ``null``. └ auto_checked_in boolean Indicates if this check-in been performed automatically by the system downloads list of objects List of ticket download options ├ output string Ticket output provider (e.g. ``pdf``, ``passbook``) diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index b9869a7c78..807dd55792 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -273,9 +273,15 @@ class AnswerSerializer(I18nAwareModelSerializer): class CheckinSerializer(I18nAwareModelSerializer): + device_id = serializers.SlugRelatedField( + source='device', + slug_field='device_id', + read_only=True, + ) + class Meta: model = Checkin - fields = ('id', 'datetime', 'list', 'auto_checked_in', 'gate', 'device', 'type') + fields = ('id', 'datetime', 'list', 'auto_checked_in', 'gate', 'device', 'device_id', 'type') class FailedCheckinSerializer(I18nAwareModelSerializer): diff --git a/src/pretix/api/views/checkin.py b/src/pretix/api/views/checkin.py index 4f374f6e0a..668b2e19c3 100644 --- a/src/pretix/api/views/checkin.py +++ b/src/pretix/api/views/checkin.py @@ -377,7 +377,7 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr Prefetch( 'positions', OrderPosition.objects.prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related('device')), 'item', 'variation', 'answers', 'answers__options', 'answers__question', ) ) diff --git a/src/pretix/api/views/media.py b/src/pretix/api/views/media.py index b6335033c7..e70f1bf769 100644 --- a/src/pretix/api/views/media.py +++ b/src/pretix/api/views/media.py @@ -78,7 +78,7 @@ class ReusableMediaViewSet(viewsets.ModelViewSet): queryset=OrderPosition.objects.select_related( 'order', 'order__event', 'order__event__organizer', 'seat', ).prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related('device')), 'answers', 'answers__options', 'answers__question', ) ), diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 050908e33b..a96c373448 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -258,7 +258,7 @@ class OrderViewSetMixin: return Prefetch( 'positions', opq.all().prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related('device')), Prefetch('item', queryset=self.request.event.items.prefetch_related( Prefetch('meta_values', ItemMetaValue.objects.select_related('property'), to_attr='meta_values_cached') )), @@ -279,7 +279,7 @@ class OrderViewSetMixin: return Prefetch( 'positions', opq.all().prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related('device')), 'item', 'variation', Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options', 'question').order_by('question__position')), 'seat', @@ -1092,7 +1092,7 @@ class OrderPositionViewSet(viewsets.ModelViewSet): 'item_meta_properties', ) qs = qs.prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related("device")), Prefetch('item', queryset=self.request.event.items.prefetch_related( Prefetch('meta_values', ItemMetaValue.objects.select_related('property'), to_attr='meta_values_cached') @@ -1111,7 +1111,7 @@ class OrderPositionViewSet(viewsets.ModelViewSet): Prefetch( 'positions', qs.prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related('device')), Prefetch('item', queryset=self.request.event.items.prefetch_related( Prefetch('meta_values', ItemMetaValue.objects.select_related('property'), to_attr='meta_values_cached') @@ -1135,7 +1135,7 @@ class OrderPositionViewSet(viewsets.ModelViewSet): ) else: qs = qs.prefetch_related( - Prefetch('checkins', queryset=Checkin.objects.all()), + Prefetch('checkins', queryset=Checkin.objects.select_related("device")), 'answers', 'answers__options', 'answers__question', ).select_related( 'item', 'order', 'order__event', 'order__event__organizer', 'seat' diff --git a/src/tests/api/test_checkin.py b/src/tests/api/test_checkin.py index 8545b15c12..3f5eb633a9 100644 --- a/src/tests/api/test_checkin.py +++ b/src/tests/api/test_checkin.py @@ -498,6 +498,7 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a 'datetime': c.datetime.isoformat().replace('+00:00', 'Z'), 'auto_checked_in': False, 'device': None, + 'device_id': None, 'gate': None, 'type': 'entry', } @@ -540,6 +541,7 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a 'datetime': c.datetime.isoformat().replace('+00:00', 'Z'), 'auto_checked_in': False, 'device': None, + 'device_id': None, 'gate': None, 'type': 'entry', } diff --git a/src/tests/api/test_orders.py b/src/tests/api/test_orders.py index fe4a6c9004..39db165a37 100644 --- a/src/tests/api/test_orders.py +++ b/src/tests/api/test_orders.py @@ -959,7 +959,7 @@ def test_refund_cancel(token_client, organizer, event, order): @pytest.mark.django_db -def test_orderposition_list(token_client, organizer, event, order, item, subevent, subevent2, question): +def test_orderposition_list(token_client, organizer, device, event, order, item, subevent, subevent2, question, django_assert_num_queries): i2 = copy.copy(item) i2.pk = None i2.save() @@ -1060,19 +1060,22 @@ def test_orderposition_list(token_client, organizer, event, order, item, subeven with scopes_disabled(): cl = event.checkin_lists.create(name="Default") - c = op.checkins.create(datetime=datetime.datetime(2017, 12, 26, 10, 0, 0, tzinfo=datetime.timezone.utc), list=cl) + c = op.checkins.create(datetime=datetime.datetime(2017, 12, 26, 10, 0, 0, tzinfo=datetime.timezone.utc), list=cl, device=device) op.checkins.create(datetime=datetime.datetime(2017, 12, 26, 10, 0, 0, tzinfo=datetime.timezone.utc), list=cl, successful=False) res['checkins'] = [{ # successful only 'id': c.pk, 'datetime': '2017-12-26T10:00:00Z', 'list': cl.pk, 'auto_checked_in': False, - 'device': None, + 'device': device.pk, + 'device_id': device.device_id, 'gate': None, 'type': 'entry' }] - resp = token_client.get( - '/api/v1/organizers/{}/events/{}/orderpositions/?has_checkin=true'.format(organizer.slug, event.slug)) + with django_assert_num_queries(15): + resp = token_client.get( + '/api/v1/organizers/{}/events/{}/orderpositions/?has_checkin=true'.format(organizer.slug, event.slug) + ) assert [res] == resp.data['results'] op.subevent = subevent