diff --git a/src/pretix/base/modelimport_orders.py b/src/pretix/base/modelimport_orders.py index ed92664af..b273cb0de 100644 --- a/src/pretix/base/modelimport_orders.py +++ b/src/pretix/base/modelimport_orders.py @@ -585,7 +585,7 @@ class SeatColumn(ImportColumn): raise ValidationError(_('Multiple matching seats were found.')) except Seat.DoesNotExist: raise ValidationError(_('No matching seat was found.')) - if not value.is_available() or value in self._cached: + if not value.is_available(sales_channel=previous_values.get('sales_channel')) or value in self._cached: raise ValidationError( _('The seat you selected has already been taken. Please select a different seat.')) self._cached.add(value) @@ -754,11 +754,11 @@ def get_order_import_columns(event): AttendeeState(event), Price(event), Secret(event), + Saleschannel(event), SeatColumn(event), ValidFrom(event), ValidUntil(event), Locale(event), - Saleschannel(event), CheckinAttentionColumn(event), CheckinTextColumn(event), Expires(event), diff --git a/src/pretix/base/services/modelimport.py b/src/pretix/base/services/modelimport.py index e5607aa55..c029e0510 100644 --- a/src/pretix/base/services/modelimport.py +++ b/src/pretix/base/services/modelimport.py @@ -118,7 +118,7 @@ def import_orders(event: Event, fileid: str, settings: dict, locale: str, user, c.assign(record.get(c.identifier), order, position, order._address) if position.seat is not None: - lock_seats.append(position.seat) + lock_seats.append((order.sales_channel, position.seat)) except (ValidationError, ImportError) as e: raise DataImportError( _('Invalid data in row {row}: {message}').format(row=i, message=str(e)) @@ -128,9 +128,9 @@ def import_orders(event: Event, fileid: str, settings: dict, locale: str, user, with transaction.atomic(): # We don't support vouchers, quotas, or memberships here, so we only need to lock if seats are in use if lock_seats: - lock_objects(lock_seats, shared_lock_objects=[event]) - for s in lock_seats: - if not s.is_available(): + lock_objects([s for c, s in lock_seats], shared_lock_objects=[event]) + for c, s in lock_seats: + if not s.is_available(sales_channel=c): raise DataImportError(_('The seat you selected has already been taken. Please select a different seat.')) save_transactions = [] diff --git a/src/tests/base/test_modelimport_orders.py b/src/tests/base/test_modelimport_orders.py index ce482534c..ca31fc400 100644 --- a/src/tests/base/test_modelimport_orders.py +++ b/src/tests/base/test_modelimport_orders.py @@ -72,7 +72,9 @@ def inputfile_factory(multiplier=1): 'I': 'Foo', 'J': '2021-06-28 11:00:00', 'K': '06221/32177-50', - 'L': 'True' + 'L': 'True', + 'M': 'baz', + 'N': 'Seat-1', }, { 'A': 'Daniel', @@ -87,6 +89,8 @@ def inputfile_factory(multiplier=1): 'J': '2021-06-28 11:00:00', 'K': '+4962213217750', 'L': 'False', + 'M': 'baz', + 'N': 'Seat-2', }, {}, { @@ -102,12 +106,14 @@ def inputfile_factory(multiplier=1): 'J': '2021-06-28 11:00:00', 'K': '', 'L': '', + 'M': 'baz', + 'N': 'Seat-3', }, ] if multiplier > 1: d = d * multiplier f = StringIO() - w = csv.DictWriter(f, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'], dialect=csv.excel) + w = csv.DictWriter(f, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'], dialect=csv.excel) w.writeheader() w.writerows(d) f.seek(0) @@ -663,20 +669,41 @@ def test_import_seat_required(user, event, item): def test_import_seat_blocked(user, event, item): settings = dict(DEFAULT_SETTINGS) settings['item'] = 'static:{}'.format(item.pk) - settings['seat'] = 'csv:D' + settings['seat'] = 'csv:N' event.seat_category_mappings.create( layout_category='Stalls', product=item ) - event.seats.create(seat_number="Test", product=item, seat_guid="Test", blocked=True) + event.seats.create(seat_number="Seat-1", product=item, seat_guid="Seat-1", blocked=True) + event.seats.create(seat_number="Seat-2", product=item, seat_guid="Seat-2", blocked=True) + event.seats.create(seat_number="Seat-3", product=item, seat_guid="Seat-3", blocked=True) with pytest.raises(DataImportError) as excinfo: import_orders.apply( args=(event.pk, inputfile_factory().id, settings, 'en', user.pk) ).get() - assert 'Error while importing value "Test" for column "Seat ID" in line "1": The seat you selected has already ' \ + assert 'Error while importing value "Seat-1" for column "Seat ID" in line "1": The seat you selected has already ' \ 'been taken. Please select a different seat.' in str(excinfo.value) +@pytest.mark.django_db +@scopes_disabled() +def test_import_seat_blocked_sales_channel(user, event, item): + settings = dict(DEFAULT_SETTINGS) + settings['item'] = 'static:{}'.format(item.pk) + settings['seat'] = 'csv:N' + settings['sales_channel'] = 'csv:M' + event.settings.seating_allow_blocked_seats_for_channel = ["baz"] + event.seat_category_mappings.create( + layout_category='Stalls', product=item + ) + event.seats.create(seat_number="Seat-1", product=item, seat_guid="Seat-1", blocked=True) + event.seats.create(seat_number="Seat-2", product=item, seat_guid="Seat-2", blocked=True) + event.seats.create(seat_number="Seat-3", product=item, seat_guid="Seat-3", blocked=True) + import_orders.apply( + args=(event.pk, inputfile_factory().id, settings, 'en', user.pk) + ).get() + + @pytest.mark.django_db @scopes_disabled() def test_import_seat_dbl(user, event, item):