diff --git a/src/pretix/api/serializers/event.py b/src/pretix/api/serializers/event.py index 0cf4d4dcb2..b2ad11732b 100644 --- a/src/pretix/api/serializers/event.py +++ b/src/pretix/api/serializers/event.py @@ -971,21 +971,21 @@ class ItemMetaPropertiesSerializer(I18nAwareModelSerializer): fields = ('id', 'name', 'default', 'required', 'allowed_values') -def prefetch_by_id(items, qs, id_attr, id_filter, target_attr): +def prefetch_by_id(items, qs, id_attr, target_attr): """ Prefetches a related object on each item in the given list of items by searching by id or another - unique field. The id value is read from the attribute on item specified in `id_attr`, searched on queryset `qs` by the - field specified in `id_filter`, and the resulting prefetched model object is stored into `target_attr` on the item. + unique field. The id value is read from the attribute on item specified in `id_attr`, searched on queryset `qs` by + the primary key, and the resulting prefetched model object is stored into `target_attr` on the item. """ ids = [getattr(item, id_attr) for item in items if getattr(item, id_attr)] if ids: - result = qs.order_by(id_filter).distinct(id_filter).in_bulk(id_list=ids, field_name=id_filter) + result = qs.in_bulk(id_list=ids) for item in items: setattr(item, target_attr, result.get(getattr(item, id_attr))) class SeatSerializer(I18nAwareModelSerializer): - orderposition = serializers.CharField(source='orderposition_id') + orderposition = serializers.IntegerField(source='orderposition_id') cartposition = serializers.IntegerField(source='cartposition_id') voucher = serializers.IntegerField(source='voucher_id') @@ -1004,11 +1004,11 @@ class SeatSerializer(I18nAwareModelSerializer): def prefetch_expanded_data(self, items, expand_fields, event): if 'orderposition' in expand_fields: - prefetch_by_id(items, OrderPosition.objects.prefetch_related('order'), 'orderposition_id', 'id', 'orderposition') + prefetch_by_id(items, OrderPosition.objects.prefetch_related('order'), 'orderposition_id', 'orderposition') if 'cartposition' in expand_fields: - prefetch_by_id(items, CartPosition.objects, 'cartposition_id', 'id', 'cartposition') + prefetch_by_id(items, CartPosition.objects, 'cartposition_id', 'cartposition') if 'voucher' in expand_fields: - prefetch_by_id(items, Voucher.objects, 'voucher_id', 'id', 'voucher') + prefetch_by_id(items, Voucher.objects, 'voucher_id', 'voucher') def __init__(self, instance, *args, **kwargs): if not kwargs.get('data'): diff --git a/src/tests/api/test_events.py b/src/tests/api/test_events.py index 4c0dae74a8..5c1918e7ca 100644 --- a/src/tests/api/test_events.py +++ b/src/tests/api/test_events.py @@ -999,6 +999,10 @@ def seatingplan(event, organizer, item): @pytest.mark.django_db def test_event_update_seating(token_client, organizer, event, item, seatingplan): + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'.format(organizer.slug, event.slug)) + assert resp.status_code == 200 + assert len(resp.data['results']) == 0 + resp = token_client.patch( '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), { @@ -1019,6 +1023,11 @@ def test_event_update_seating(token_client, organizer, event, item, seatingplan) assert m.layout_category == 'Stalls' assert m.product == item + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'.format(organizer.slug, event.slug)) + assert resp.status_code == 200 + assert len(resp.data['results']) == 3 + assert all(seat['product'] == item.pk for seat in resp.data['results']) + @pytest.mark.django_db def test_event_update_seating_invalid_product(token_client, organizer, event, item, seatingplan): @@ -1514,3 +1523,47 @@ def test_patch_event_settings_file(token_client, organizer, event): ) assert resp.status_code == 200 assert resp.data['logo_image'] is None + + +@pytest.mark.django_db +def test_event_block_unblock_seat(token_client, organizer, event, seatingplan, item): + resp = token_client.patch( + '/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug), + { + "seating_plan": seatingplan.pk, + "seat_category_mapping": { + "Stalls": item.pk + } + }, + format='json' + ) + assert resp.status_code == 200 + event.refresh_from_db() + + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/'.format(organizer.slug, event.slug)) + assert resp.status_code == 200 + + seat_id = resp.data['results'][0]['id'] + resp = token_client.patch( + '/api/v1/organizers/{}/events/{}/seats/{}/'.format(organizer.slug, event.slug, seat_id), + { + "blocked": True, + }, + format='json' + ) + assert resp.status_code == 200 + assert resp.data['blocked'] is True + + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/{}/?expand=orderposition&expand=cartposition&expand=voucher'.format(organizer.slug, event.slug, seat_id)) + assert resp.status_code == 200 + assert resp.data['blocked'] is True + + resp = token_client.patch( + '/api/v1/organizers/{}/events/{}/seats/{}/'.format(organizer.slug, event.slug, seat_id), + { + "blocked": False, + }, + format='json' + ) + assert resp.status_code == 200 + assert resp.data['blocked'] is False diff --git a/src/tests/api/test_order_create.py b/src/tests/api/test_order_create.py index b52fbad1cb..029b227ab2 100644 --- a/src/tests/api/test_order_create.py +++ b/src/tests/api/test_order_create.py @@ -2010,6 +2010,15 @@ def test_order_create_with_seat(token_client, organizer, event, item, quota, sea p = o.positions.first() assert p.seat == seat + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/{}/'.format(organizer.slug, event.slug, seat.pk)) + assert resp.status_code == 200 + assert resp.data['orderposition'] == p.pk + + resp = token_client.get('/api/v1/organizers/{}/events/{}/seats/{}/?expand=orderposition'.format(organizer.slug, event.slug, seat.pk)) + assert resp.status_code == 200 + assert resp.data['orderposition']['id'] == p.pk + + @pytest.mark.django_db def test_order_create_with_blocked_seat_allowed(token_client, organizer, event, item, quota, seat, question): diff --git a/src/tests/api/test_permissions.py b/src/tests/api/test_permissions.py index a96054c206..d85e0c99f0 100644 --- a/src/tests/api/test_permissions.py +++ b/src/tests/api/test_permissions.py @@ -54,6 +54,7 @@ event_urls = [ (None, 'taxrules/'), ('can_view_orders', 'waitinglistentries/'), ('can_view_orders', 'checkinlists/'), + (None, 'seats/'), ] event_permission_sub_urls = [ @@ -191,6 +192,8 @@ event_permission_sub_urls = [ ('post', 'can_change_event_settings', 'item_meta_properties/', 400), ('patch', 'can_change_event_settings', 'item_meta_properties/0/', 404), ('delete', 'can_change_event_settings', 'item_meta_properties/0/', 404), + ('get', None, 'seats/1/', 404), + ('patch', 'can_change_event_settings', 'seats/1/', 404), ] org_permission_sub_urls = [