diff --git a/src/pretix/base/orderimport.py b/src/pretix/base/orderimport.py
index ba5a1ec0c8..09ef25c35e 100644
--- a/src/pretix/base/orderimport.py
+++ b/src/pretix/base/orderimport.py
@@ -19,6 +19,7 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# .
#
+import datetime
import re
from collections import defaultdict
from decimal import Decimal, DecimalException
@@ -40,7 +41,7 @@ from pretix.base.channels import get_all_sales_channels
from pretix.base.forms.questions import guess_country
from pretix.base.models import (
ItemVariation, OrderPosition, Question, QuestionAnswer, QuestionOption,
- Seat,
+ Seat, SubEvent,
)
from pretix.base.services.pricing import get_price
from pretix.base.settings import (
@@ -160,6 +161,10 @@ class SubeventColumn(ImportColumn):
verbose_name = pgettext_lazy('subevents', 'Date')
default_value = None
+ def __init__(self, *args, **kwargs):
+ self._subevent_cache = {}
+ super().__init__(*args, **kwargs)
+
@cached_property
def subevents(self):
return list(self.event.subevents.filter(active=True).order_by('date_from'))
@@ -172,6 +177,30 @@ class SubeventColumn(ImportColumn):
def clean(self, value, previous_values):
if not value:
raise ValidationError(pgettext("subevent", "You need to select a date."))
+
+ if value in self._subevent_cache:
+ return self._subevent_cache[value]
+
+ input_formats = formats.get_format('DATETIME_INPUT_FORMATS', use_l10n=True)
+ for format in input_formats:
+ try:
+ d = datetime.datetime.strptime(value, format)
+ d = self.event.timezone.localize(d)
+ try:
+ se = self.event.subevents.get(
+ active=True,
+ date_from__gt=d - datetime.timedelta(seconds=1),
+ date_from__lt=d + datetime.timedelta(seconds=1),
+ )
+ self._subevent_cache[value] = se
+ return se
+ except SubEvent.DoesNotExist:
+ raise ValidationError(pgettext("subevent", "No matching date was found."))
+ except SubEvent.MultipleObjectsReturned:
+ raise ValidationError(pgettext("subevent", "Multiple matching dates were found."))
+ except (ValueError, TypeError):
+ continue
+
matches = [
p for p in self.subevents
if str(p.pk) == value or any(
@@ -181,6 +210,8 @@ class SubeventColumn(ImportColumn):
raise ValidationError(pgettext("subevent", "No matching date was found."))
if len(matches) > 1:
raise ValidationError(pgettext("subevent", "Multiple matching dates were found."))
+
+ self._subevent_cache[value] = matches[0]
return matches[0]
def assign(self, value, order, position, invoice_address, **kwargs):
diff --git a/src/tests/base/test_orderimport.py b/src/tests/base/test_orderimport.py
index b083810281..1c5534e9fc 100644
--- a/src/tests/base/test_orderimport.py
+++ b/src/tests/base/test_orderimport.py
@@ -20,6 +20,7 @@
# .
#
import csv
+import datetime
from decimal import Decimal
from io import StringIO
@@ -68,6 +69,7 @@ def inputfile_factory():
'G': 'US',
'H': 'Texas',
'I': 'Foo',
+ 'J': '2021-06-28 11:00:00',
},
{
'A': 'Daniel',
@@ -79,6 +81,7 @@ def inputfile_factory():
'G': 'DE',
'H': '',
'I': 'Bar',
+ 'J': '2021-06-28 11:00:00',
},
{
'A': 'Anke',
@@ -90,10 +93,11 @@ def inputfile_factory():
'G': 'AU',
'H': '',
'I': 'Foo,Bar',
+ 'J': '2021-06-28 11:00:00',
},
]
f = StringIO()
- w = csv.DictWriter(f, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', "I"], dialect=csv.excel)
+ w = csv.DictWriter(f, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], dialect=csv.excel)
w.writeheader()
w.writerows(d)
f.seek(0)
@@ -675,7 +679,7 @@ def test_import_subevent_required(user, event, item):
@pytest.mark.django_db
@scopes_disabled()
-def test_import_subevent(user, event, item):
+def test_import_subevent_by_name(user, event, item):
settings = dict(DEFAULT_SETTINGS)
event.has_subevents = True
event.save()
@@ -689,6 +693,23 @@ def test_import_subevent(user, event, item):
assert OrderPosition.objects.filter(subevent=s).count() == 3
+@pytest.mark.django_db
+@scopes_disabled()
+def test_import_subevent_by_date(user, event, item):
+ settings = dict(DEFAULT_SETTINGS)
+ event.has_subevents = True
+ event.save()
+ event.settings.timezone = 'Europe/Berlin'
+ s = event.subevents.create(name='Test', date_from=event.timezone.localize(datetime.datetime(2021, 6, 28, 11, 0, 0, 0)), active=True)
+ settings['item'] = 'static:{}'.format(item.pk)
+ settings['subevent'] = 'csv:J'
+
+ 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):