diff --git a/src/pretix/api/serializers/exporters.py b/src/pretix/api/serializers/exporters.py index f541f758a1..ff1bb6464c 100644 --- a/src/pretix/api/serializers/exporters.py +++ b/src/pretix/api/serializers/exporters.py @@ -133,37 +133,43 @@ class JobRunSerializer(serializers.Serializer): return not bool(self._errors) +class ExportFormDataField(serializers.Field): + def get_attribute(self, instance): + return (instance.export_identifier, instance.export_form_data) + + def to_representation(self, value): + export_identifier, export_form_data = value + exporter = self.context['exporters'].get(export_identifier) + if exporter: + return JobRunSerializer(exporter=exporter).to_representation(export_form_data) + else: + return export_form_data + + def get_value(self, dictionary): + return dictionary + + def to_internal_value(self, data): + if "export_form_data" in data: + identifier = data.get('export_identifier', self.parent.instance.export_identifier if self.parent.instance else None) + exporter = self.context['exporters'].get(identifier) + if exporter: + return JobRunSerializer(exporter=exporter).to_internal_value(data["export_form_data"]) + else: + return data['export_form_data'] + + class ScheduledExportSerializer(serializers.ModelSerializer): schedule_next_run = serializers.DateTimeField(read_only=True) export_identifier = serializers.ChoiceField(choices=[]) locale = serializers.ChoiceField(choices=settings.LANGUAGES, default='en') owner = serializers.SlugRelatedField(slug_field='email', read_only=True) error_counter = serializers.IntegerField(read_only=True) + export_form_data = ExportFormDataField() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['export_identifier'].choices = [(e, e) for e in self.context['exporters']] - def validate(self, attrs): - if attrs.get("export_form_data"): - identifier = attrs.get('export_identifier', self.instance.export_identifier if self.instance else None) - exporter = self.context['exporters'].get(identifier) - if exporter: - try: - attrs["export_form_data"] = JobRunSerializer(exporter=exporter).to_internal_value(attrs["export_form_data"]) - except ValidationError as e: - raise ValidationError({"export_form_data": e.detail}) - else: - raise ValidationError({"export_identifier": ["Unknown exporter."]}) - return attrs - - def to_representation(self, instance): - repr = super().to_representation(instance) - exporter = self.context['exporters'].get(instance.export_identifier) - if exporter: - repr["export_form_data"] = JobRunSerializer(exporter=exporter).to_representation(repr["export_form_data"]) - return repr - def validate_mail_additional_recipients(self, value): d = value.replace(' ', '') if len(d.split(',')) > 25: diff --git a/src/pretix/api/serializers/forms.py b/src/pretix/api/serializers/forms.py index 00459016c6..08ec53a5b1 100644 --- a/src/pretix/api/serializers/forms.py +++ b/src/pretix/api/serializers/forms.py @@ -45,6 +45,12 @@ class PrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField): return value return super().to_representation(value) + def to_internal_value(self, data): + value = super().to_internal_value(data) + if value is not None: + return value.pk + return value + class FormFieldWrapperField(serializers.Field): def __init__(self, *args, **kwargs): diff --git a/src/pretix/plugins/checkinlists/exporters.py b/src/pretix/plugins/checkinlists/exporters.py index 21739e1048..8bd8763fc9 100644 --- a/src/pretix/plugins/checkinlists/exporters.py +++ b/src/pretix/plugins/checkinlists/exporters.py @@ -82,7 +82,8 @@ class CheckInListMixin(BaseExporter): widget=forms.RadioSelect( attrs={'class': 'scrolling-choice'} ), - initial=self.event.checkin_lists.first() + initial=self.event.checkin_lists.first(), + required=True )), ('date_range', DateFrameField( @@ -143,7 +144,6 @@ class CheckInListMixin(BaseExporter): if not self.event.has_subevents: del d['date_range'] - d['list'].queryset = self.event.checkin_lists.all() d['list'].widget = Select2( attrs={ 'data-model-select2': 'generic', @@ -155,7 +155,6 @@ class CheckInListMixin(BaseExporter): } ) d['list'].widget.choices = d['list'].choices - d['list'].required = True return d diff --git a/src/tests/api/conftest.py b/src/tests/api/conftest.py index 031b6a7c52..a4d617b22a 100644 --- a/src/tests/api/conftest.py +++ b/src/tests/api/conftest.py @@ -212,4 +212,17 @@ def membership_type(organizer): return organizer.membership_types.create(name='foo') +@pytest.fixture +def clist(event, item): + c = event.checkin_lists.create(name="Default", all_products=False) + c.limit_products.add(item) + return c + + +@pytest.fixture +def clist_all(event, item): + c = event.checkin_lists.create(name="Default", all_products=True) + return c + + utils.setup_databases = scopes_disabled()(utils.setup_databases) diff --git a/src/tests/api/test_checkin.py b/src/tests/api/test_checkin.py index f829eb3422..63c38df34e 100644 --- a/src/tests/api/test_checkin.py +++ b/src/tests/api/test_checkin.py @@ -252,19 +252,6 @@ TEST_HISTORY_RES = { } -@pytest.fixture -def clist(event, item): - c = event.checkin_lists.create(name="Default", all_products=False) - c.limit_products.add(item) - return c - - -@pytest.fixture -def clist_all(event, item): - c = event.checkin_lists.create(name="Default", all_products=True) - return c - - @pytest.mark.django_db def test_list_list(token_client, organizer, event, clist, item, subevent, django_assert_num_queries): res = dict(TEST_LIST_RES) diff --git a/src/tests/api/test_exporters.py b/src/tests/api/test_exporters.py index 7282def74f..23495065fe 100644 --- a/src/tests/api/test_exporters.py +++ b/src/tests/api/test_exporters.py @@ -1079,3 +1079,18 @@ def test_event_edit_restrictions(client, event, organizer, user, team): assert _get_and_patch_event_export(user2_client, s2) assert _get_and_patch_event_export(team1_client, s2) assert _get_and_patch_event_export(user1_client, s2) + + +@pytest.mark.django_db +def test_event_checkinlist_patch(user_client, organizer, event, user, event_scheduled_export, clist): + event_scheduled_export.export_identifier = "checkinlistpdf" + event_scheduled_export.save() + + resp = user_client.patch( + '/api/v1/organizers/{}/events/{}/scheduled_exports/{}/'.format(organizer.slug, event.slug, event_scheduled_export.id), + data={ + "export_form_data": {"list": clist.pk}, + }, + format='json', + ) + assert resp.status_code == 200