mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Allow to import orders (#1516)
* Allow to import orders * seats, subevents * Plugin support * Add docs * Warn about lack of quota handling * Control interface test * Test skeleton * First tests for the impotr columns * Add tests for all columns * Fix question validation
This commit is contained in:
@@ -2277,7 +2277,9 @@ def test_question_answer_validation_multiple_choice():
|
||||
assert q.clean_answer([str(o1.pk), str(o2.pk)]) == [o1, o2]
|
||||
assert q.clean_answer([str(o1.pk)]) == [o1]
|
||||
assert q.clean_answer([o1.pk]) == [o1]
|
||||
assert q.clean_answer([o1.pk, o3.pk]) == [o1]
|
||||
assert q.clean_answer([o1.pk, o3.pk + 1000]) == [o1]
|
||||
with pytest.raises(ValidationError):
|
||||
assert q.clean_answer([o1.pk, o3.pk]) == [o1]
|
||||
with pytest.raises(ValidationError):
|
||||
assert q.clean_answer([o1.pk, o3.pk + 1000]) == [o1]
|
||||
with pytest.raises(ValidationError):
|
||||
assert q.clean_answer([o1.pk, 'FOO']) == [o1]
|
||||
|
||||
688
src/tests/base/test_orderimport.py
Normal file
688
src/tests/base/test_orderimport.py
Normal file
@@ -0,0 +1,688 @@
|
||||
import csv
|
||||
from _decimal import Decimal
|
||||
from io import StringIO
|
||||
|
||||
import pytest
|
||||
from django.core.files.base import ContentFile
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scopes_disabled
|
||||
from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.base.models import (
|
||||
CachedFile, Event, Item, Order, OrderPayment, OrderPosition, Organizer,
|
||||
Question, QuestionAnswer, User,
|
||||
)
|
||||
from pretix.base.services.orderimport import DataImportError, import_orders
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def event():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
return event
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def item(event):
|
||||
return Item.objects.create(event=event, name="Ticket", default_price=23)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user():
|
||||
return User.objects.create_user('test@localhost', 'test')
|
||||
|
||||
|
||||
def inputfile_factory():
|
||||
d = [
|
||||
{
|
||||
'A': 'Dieter',
|
||||
'B': 'Schneider',
|
||||
'C': 'schneider@example.org',
|
||||
'D': 'Test',
|
||||
'E': 'Foo',
|
||||
'F': '0.00',
|
||||
'G': 'US',
|
||||
'H': 'Texas',
|
||||
'I': 'Foo',
|
||||
},
|
||||
{
|
||||
'A': 'Daniel',
|
||||
'B': 'Wulf',
|
||||
'C': 'daniel@example.org',
|
||||
'D': 'Test',
|
||||
'E': 'Bar',
|
||||
'F': '0.00',
|
||||
'G': 'DE',
|
||||
'H': '',
|
||||
'I': 'Bar',
|
||||
},
|
||||
{
|
||||
'A': 'Anke',
|
||||
'B': 'Müller',
|
||||
'C': '',
|
||||
'D': 'Test',
|
||||
'E': 'Baz',
|
||||
'F': '0.00',
|
||||
'G': 'AU',
|
||||
'H': '',
|
||||
'I': 'Foo,Bar',
|
||||
},
|
||||
]
|
||||
f = StringIO()
|
||||
w = csv.DictWriter(f, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', "I"], dialect=csv.excel)
|
||||
w.writeheader()
|
||||
w.writerows(d)
|
||||
f.seek(0)
|
||||
c = CachedFile.objects.create(type="text/csv", filename="input.csv")
|
||||
c.file.save("input.csv", ContentFile(f.read()))
|
||||
return c
|
||||
|
||||
|
||||
DEFAULT_SETTINGS = {
|
||||
'orders': 'many',
|
||||
'testmode': False,
|
||||
'status': 'paid',
|
||||
'email': 'empty',
|
||||
'variation': 'empty',
|
||||
'invoice_address_company': 'empty',
|
||||
'invoice_address_name_full_name': 'empty',
|
||||
'invoice_address_street': 'empty',
|
||||
'invoice_address_zipcode': 'empty',
|
||||
'invoice_address_city': 'empty',
|
||||
'invoice_address_country': 'static:DE',
|
||||
'invoice_address_state': 'empty',
|
||||
'invoice_address_vat_id': 'empty',
|
||||
'invoice_address_internal_reference': 'empty',
|
||||
'attendee_name_full_name': 'empty',
|
||||
'attendee_email': 'empty',
|
||||
'price': 'empty',
|
||||
'secret': 'empty',
|
||||
'locale': 'static:en',
|
||||
'sales_channel': 'static:web',
|
||||
'comment': 'empty'
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_simple(event, item, user):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert event.orders.count() == 3
|
||||
assert OrderPosition.objects.count() == 3
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_as_one_order(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['orders'] = 'one'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert event.orders.count() == 1
|
||||
o = event.orders.get()
|
||||
assert o.positions.count() == 3
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_in_test_mode(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['testmode'] = True
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert event.orders.last().testmode
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_not_in_test_mode(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['testmode'] = False
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert not event.orders.last().testmode
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_pending(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['status'] = 'pending'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
o = event.orders.last()
|
||||
assert o.status == Order.STATUS_PENDING
|
||||
assert o.total == Decimal('23.00')
|
||||
assert not o.payments.exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_paid_generate_invoice(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['status'] = 'paid'
|
||||
event.settings.invoice_generate = 'paid'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
o = event.orders.last()
|
||||
assert o.status == Order.STATUS_PAID
|
||||
assert o.total == Decimal('23.00')
|
||||
p = o.payments.first()
|
||||
assert p.provider == 'manual'
|
||||
assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED
|
||||
assert o.invoices.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_free(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['price'] = 'csv:F'
|
||||
settings['status'] = 'pending'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
o = event.orders.last()
|
||||
assert o.status == Order.STATUS_PAID
|
||||
assert o.total == Decimal('0.00')
|
||||
p = o.payments.first()
|
||||
assert p.provider == 'free'
|
||||
assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_email(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['email'] = 'csv:C'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert event.orders.filter(email="schneider@example.org").exists()
|
||||
assert event.orders.filter(email="daniel@example.org").exists()
|
||||
assert event.orders.filter(email__isnull=True).count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_email_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['email'] = 'csv:A'
|
||||
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 "Dieter" for column "E-mail address" in line "1": Enter a valid email address.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_attendee_email(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['attendee_email'] = 'csv:C'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert OrderPosition.objects.filter(attendee_email="schneider@example.org").exists()
|
||||
assert OrderPosition.objects.filter(attendee_email__isnull=True).count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_attendee_email_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['attendee_email'] = 'csv:A'
|
||||
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 "Dieter" for column "Attendee e-mail address" in line "1": Enter a valid email address.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_product(user, event, item):
|
||||
i = Item.objects.create(
|
||||
event=event,
|
||||
name=LazyI18nString({'de': 'Foo', 'en': 'Bar'}),
|
||||
internal_name='Baz',
|
||||
default_price=23,
|
||||
)
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'csv:E'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert OrderPosition.objects.filter(item=i).count() == 3
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_product_unknown(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'csv:A'
|
||||
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 "Dieter" for column "Product" in line "1": No matching product was found.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_product_dupl(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'csv:E'
|
||||
Item.objects.create(
|
||||
event=event,
|
||||
name='Foo',
|
||||
default_price=23,
|
||||
)
|
||||
Item.objects.create(
|
||||
event=event,
|
||||
name='Foo',
|
||||
default_price=23,
|
||||
)
|
||||
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 "Foo" for column "Product" in line "1": Multiple matching products were found.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_variation_required(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
item.variations.create(value='Default')
|
||||
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 "" for column "Product variation" in line "1": You need to select a variation for this product.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_variation_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['variation'] = 'csv:E'
|
||||
item.variations.create(value='Default')
|
||||
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 "Foo" for column "Product variation" in line "1": No matching variation was found.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_variation_dynamic(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['variation'] = 'csv:E'
|
||||
v1 = item.variations.create(value='Foo')
|
||||
v2 = item.variations.create(value=LazyI18nString({'en': 'Bar'}))
|
||||
v3 = item.variations.create(value='Baz')
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert OrderPosition.objects.filter(variation=v1).count() == 1
|
||||
assert OrderPosition.objects.filter(variation=v2).count() == 1
|
||||
assert OrderPosition.objects.filter(variation=v3).count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_company(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['email'] = 'csv:C'
|
||||
settings['invoice_address_company'] = 'csv:C'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert event.orders.get(email='schneider@example.org').invoice_address.company == 'schneider@example.org'
|
||||
assert event.orders.get(email='schneider@example.org').invoice_address.is_business
|
||||
assert event.orders.get(email__isnull=True).invoice_address.company == ''
|
||||
assert not event.orders.get(email__isnull=True).invoice_address.is_business
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_name_parts(user, event, item):
|
||||
event.settings.name_scheme = 'given_family'
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['email'] = 'csv:C'
|
||||
settings['invoice_address_name_given_name'] = 'csv:A'
|
||||
settings['invoice_address_name_family_name'] = 'csv:B'
|
||||
settings['attendee_name_given_name'] = 'csv:A'
|
||||
settings['attendee_name_family_name'] = 'csv:B'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
o = event.orders.get(email='schneider@example.org')
|
||||
assert o.invoice_address.name_parts == {
|
||||
'_scheme': 'given_family',
|
||||
'given_name': 'Dieter',
|
||||
'family_name': 'Schneider'
|
||||
}
|
||||
assert o.invoice_address.name_cached == 'Dieter Schneider'
|
||||
assert o.positions.first().attendee_name_parts == {
|
||||
'_scheme': 'given_family',
|
||||
'given_name': 'Dieter',
|
||||
'family_name': 'Schneider'
|
||||
}
|
||||
assert o.positions.first().attendee_name_cached == 'Dieter Schneider'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_country(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['invoice_address_country'] = 'csv:G'
|
||||
settings['email'] = 'csv:C'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert str(event.orders.get(email='schneider@example.org').invoice_address.country) == 'US'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_country_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['invoice_address_country'] = 'csv:A'
|
||||
settings['email'] = 'csv:C'
|
||||
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 "Dieter" for column "Invoice address: Country" in line "1": Please enter a valid country code.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_state(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['invoice_address_country'] = 'csv:G'
|
||||
settings['invoice_address_state'] = 'csv:H'
|
||||
settings['email'] = 'csv:C'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
)
|
||||
assert str(event.orders.get(email='schneider@example.org').invoice_address.country) == 'US'
|
||||
assert str(event.orders.get(email='schneider@example.org').invoice_address.state) == 'TX'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_state_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['invoice_address_country'] = 'static:AU'
|
||||
settings['invoice_address_state'] = 'csv:H'
|
||||
settings['email'] = 'csv:C'
|
||||
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 "Texas" for column "Invoice address: State" in line "1": Please enter a valid state.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_saleschannel_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['sales_channel'] = 'csv:A'
|
||||
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 "Dieter" for column "Sales channel" in line "1": Please enter a valid sales channel.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_locale_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['locale'] = 'static:de' # not enabled on this event
|
||||
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 "de" for column "Order locale" in line "1": Please enter a valid language code.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_price_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['price'] = 'csv:A'
|
||||
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 "Dieter" for column "Price" in line "1": You ' \
|
||||
'entered an invalid number.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_secret(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['secret'] = 'csv:A'
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert OrderPosition.objects.filter(secret="Dieter").count() == 1
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_secret_dupl(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['secret'] = 'csv:D'
|
||||
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 "Ticket code" in line "2": You cannot assign a position ' \
|
||||
'secret that already exists.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_seat_required(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
|
||||
event.seat_category_mappings.create(
|
||||
layout_category='Stalls', product=item
|
||||
)
|
||||
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 "" for column "Seat ID" in line "1": You need to select ' \
|
||||
'a specific seat.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_seat_blocked(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['seat'] = 'csv:D'
|
||||
|
||||
event.seat_category_mappings.create(
|
||||
layout_category='Stalls', product=item
|
||||
)
|
||||
event.seats.create(name="Test", product=item, seat_guid="Test", 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 ' \
|
||||
'been taken. Please select a different seat.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_seat_dbl(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['seat'] = 'csv:D'
|
||||
|
||||
event.seat_category_mappings.create(
|
||||
layout_category='Stalls', product=item
|
||||
)
|
||||
event.seats.create(name="Test", product=item, seat_guid="Test")
|
||||
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 "2": 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(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['seat'] = 'csv:E'
|
||||
|
||||
event.seat_category_mappings.create(
|
||||
layout_category='Stalls', product=item
|
||||
)
|
||||
s1 = event.seats.create(name="Foo", product=item, seat_guid="Foo")
|
||||
s2 = event.seats.create(name="Bar", product=item, seat_guid="Bar")
|
||||
s3 = event.seats.create(name="Baz", product=item, seat_guid="Baz")
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert not s1.is_available()
|
||||
assert not s2.is_available()
|
||||
assert not s3.is_available()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_subevent_invalid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
event.subevents.create(name='Foo', date_from=now(), active=True)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['subevent'] = 'csv:E'
|
||||
|
||||
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 "Bar" for column "Date" in line "2": No matching date was found.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_subevent_required(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
|
||||
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 "" for column "Date" in line "1": You need to select a date.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_subevent(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
event.has_subevents = True
|
||||
event.save()
|
||||
s = event.subevents.create(name='Test', date_from=now(), active=True)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['subevent'] = 'csv:D'
|
||||
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert OrderPosition.objects.filter(subevent=s).count() == 3
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_question_validate(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
q = event.questions.create(question='Foo', type=Question.TYPE_NUMBER)
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['question_{}'.format(q.pk)] = 'csv:D'
|
||||
|
||||
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 "Question: Foo" in line "1": Invalid number input.' in str(excinfo.value)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@scopes_disabled()
|
||||
def test_import_question_valid(user, event, item):
|
||||
settings = dict(DEFAULT_SETTINGS)
|
||||
q = event.questions.create(question='Foo', type=Question.TYPE_CHOICE_MULTIPLE)
|
||||
o1 = q.options.create(answer='Foo', identifier='Foo')
|
||||
o2 = q.options.create(answer='Bar', identifier='Bar')
|
||||
settings['item'] = 'static:{}'.format(item.pk)
|
||||
settings['attendee_email'] = 'csv:C'
|
||||
settings['question_{}'.format(q.pk)] = 'csv:I'
|
||||
|
||||
import_orders.apply(
|
||||
args=(event.pk, inputfile_factory().id, settings, 'en', user.pk)
|
||||
).get()
|
||||
assert QuestionAnswer.objects.filter(question=q).count() == 3
|
||||
a1 = OrderPosition.objects.get(attendee_email='schneider@example.org').answers.first()
|
||||
assert a1.question == q
|
||||
assert list(a1.options.all()) == [o1]
|
||||
a3 = OrderPosition.objects.get(attendee_email__isnull=True).answers.first()
|
||||
assert a3.question == q
|
||||
assert set(a3.options.all()) == {o1, o2}
|
||||
|
||||
# TODO: validate question
|
||||
46
src/tests/control/test_orderimport.py
Normal file
46
src/tests/control/test_orderimport.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import pytest
|
||||
from bs4 import BeautifulSoup
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import Event, Organizer, Team, User
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
|
||||
t = Team.objects.create(organizer=event.organizer, can_view_orders=True, can_change_orders=True)
|
||||
t.members.add(user)
|
||||
t.limit_events.add(event)
|
||||
return event, user
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_import_csv_file(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
r = client.get('/control/event/dummy/dummy/orders/import/')
|
||||
assert r.status_code == 200
|
||||
|
||||
file = SimpleUploadedFile('file.csv', """First name,Last name,Email
|
||||
Dieter,Schneider,schneider@example.org
|
||||
Daniel,Wulf,daniel@example.org
|
||||
Daniel,Wulf,daniel@example.org
|
||||
Anke,Müller,anke@example.net
|
||||
|
||||
""".encode("utf-8"), content_type="text/csv")
|
||||
|
||||
r = client.post('/control/event/dummy/dummy/orders/import/', {
|
||||
'file': file
|
||||
}, follow=True)
|
||||
doc = BeautifulSoup(r.content, "lxml")
|
||||
assert doc.select("select[name=orders]")
|
||||
assert doc.select("select[name=status]")
|
||||
assert doc.select("select[name=attendee_email]")
|
||||
assert b"Dieter" in r.content
|
||||
assert b"daniel@example.org" in r.content
|
||||
assert b"Anke" not in r.content
|
||||
@@ -115,6 +115,7 @@ event_urls = [
|
||||
"orders/ABC/delete",
|
||||
"orders/ABC/",
|
||||
"orders/",
|
||||
"orders/import/",
|
||||
"checkinlists/",
|
||||
"checkinlists/1/",
|
||||
"checkinlists/1/change",
|
||||
@@ -280,6 +281,8 @@ event_permission_urls = [
|
||||
("can_change_orders", "orders/FOO/delete", 302),
|
||||
("can_change_orders", "orders/FOO/comment", 405),
|
||||
("can_change_orders", "orders/FOO/locale", 200),
|
||||
("can_change_orders", "orders/import/", 200),
|
||||
("can_change_orders", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404),
|
||||
("can_view_orders", "orders/FOO/answer/5/", 404),
|
||||
("can_change_vouchers", "vouchers/add", 200),
|
||||
("can_change_orders", "requiredactions/", 200),
|
||||
|
||||
Reference in New Issue
Block a user