Order import: Improve subevent handling

This commit is contained in:
Raphael Michel
2021-06-28 12:13:45 +02:00
parent 93c791e16f
commit 60f0e297e3
2 changed files with 55 additions and 3 deletions

View File

@@ -19,6 +19,7 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
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):

View File

@@ -20,6 +20,7 @@
# <https://www.gnu.org/licenses/>.
#
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):