mirror of
https://github.com/pretix/pretix.git
synced 2025-12-05 21:32:28 +00:00
Compare commits
9 Commits
subevent-f
...
v1.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d64917a65e | ||
|
|
dde95b0c5c | ||
|
|
596beb99be | ||
|
|
0581d82306 | ||
|
|
44ba1904f6 | ||
|
|
a5c7c9dd1e | ||
|
|
6d7ada4836 | ||
|
|
96fa4d68bc | ||
|
|
a0d3cafc94 |
@@ -2,11 +2,32 @@ before_script:
|
||||
tests:
|
||||
stage: test
|
||||
script:
|
||||
- virtualenv-3.4 env
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh style
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh tests
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh doctests
|
||||
tags:
|
||||
- python3
|
||||
pypi:
|
||||
stage: release
|
||||
script:
|
||||
- cp /keys/.pypirc ~/.pypirc
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
- cd src
|
||||
- python setup.py sdist upload
|
||||
- python setup.py bdist_wheel upload
|
||||
tags:
|
||||
- python3
|
||||
only:
|
||||
- release
|
||||
artifacts:
|
||||
paths:
|
||||
- src/dist/
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- release
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "1.1.0"
|
||||
__version__ = "1.1.3"
|
||||
|
||||
@@ -5,7 +5,7 @@ from django.core.validators import RegexValidator
|
||||
from django.utils.timezone import get_current_timezone_name
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from i18nfield.forms import I18nFormField, I18nTextarea
|
||||
from pytz import common_timezones
|
||||
from pytz import common_timezones, timezone
|
||||
|
||||
from pretix.base.forms import I18nModelForm, SettingsForm
|
||||
from pretix.base.models import Event, Organizer
|
||||
@@ -76,12 +76,27 @@ class EventWizardBasicsForm(I18nModelForm):
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
if data['locale'] not in self.locales:
|
||||
if data.get('locale') not in self.locales:
|
||||
raise ValidationError({
|
||||
'locale': _('Your default locale must also be enabled for your event (see box above).')
|
||||
})
|
||||
if data.get('timezone') not in common_timezones:
|
||||
raise ValidationError({
|
||||
'timezone': _('Your default locale must be specified.')
|
||||
})
|
||||
|
||||
# change timezone
|
||||
zone = timezone(data.get('timezone'))
|
||||
data['date_from'] = self.reset_timezone(zone, data.get('date_from'))
|
||||
data['date_to'] = self.reset_timezone(zone, data.get('date_to'))
|
||||
data['presale_start'] = self.reset_timezone(zone, data.get('presale_start'))
|
||||
data['presale_end'] = self.reset_timezone(zone, data.get('presale_end'))
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def reset_timezone(tz, dt):
|
||||
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
|
||||
|
||||
def clean_slug(self):
|
||||
slug = self.cleaned_data['slug']
|
||||
if Event.objects.filter(slug=slug, organizer=self.organizer).exists():
|
||||
|
||||
@@ -117,7 +117,18 @@ class ItemCreateForm(I18nModelForm):
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.cleaned_data.get('copy_from'):
|
||||
self.instance.category = self.cleaned_data['copy_from'].category
|
||||
self.instance.description = self.cleaned_data['copy_from'].description
|
||||
self.instance.active = self.cleaned_data['copy_from'].active
|
||||
self.instance.available_from = self.cleaned_data['copy_from'].available_from
|
||||
self.instance.available_until = self.cleaned_data['copy_from'].available_until
|
||||
self.instance.require_voucher = self.cleaned_data['copy_from'].require_voucher
|
||||
self.instance.hide_without_voucher = self.cleaned_data['copy_from'].hide_without_voucher
|
||||
self.instance.allow_cancel = self.cleaned_data['copy_from'].allow_cancel
|
||||
|
||||
instance = super().save(*args, **kwargs)
|
||||
|
||||
if self.cleaned_data.get('has_variations'):
|
||||
if self.cleaned_data.get('copy_from') and self.cleaned_data.get('copy_from').has_variations:
|
||||
for variation in self.cleaned_data['copy_from'].variations.all():
|
||||
@@ -128,8 +139,9 @@ class ItemCreateForm(I18nModelForm):
|
||||
item=instance, value=__('Standard')
|
||||
)
|
||||
|
||||
for question in Question.objects.filter(items=self.cleaned_data.get('copy_from')):
|
||||
question.items.add(instance)
|
||||
if self.cleaned_data.get('copy_from'):
|
||||
for question in self.cleaned_data['copy_from'].questions.all():
|
||||
question.items.add(instance)
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import FormView, ListView
|
||||
from django.views.generic.base import TemplateView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from pytz import timezone
|
||||
|
||||
from pretix.base.forms import I18nModelForm
|
||||
from pretix.base.models import (
|
||||
@@ -88,10 +89,21 @@ class EventUpdate(EventPermissionRequiredMixin, UpdateView):
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if form.is_valid() and self.sform.is_valid():
|
||||
# reset timezone
|
||||
zone = timezone(self.sform.cleaned_data['timezone'])
|
||||
event = form.instance
|
||||
event.date_from = self.reset_timezone(zone, event.date_from)
|
||||
event.date_to = self.reset_timezone(zone, event.date_to)
|
||||
event.presale_start = self.reset_timezone(zone, event.presale_start)
|
||||
event.presale_end = self.reset_timezone(zone, event.presale_end)
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
@staticmethod
|
||||
def reset_timezone(tz, dt):
|
||||
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
|
||||
|
||||
|
||||
class EventPlugins(EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
||||
model = Event
|
||||
|
||||
@@ -766,15 +766,6 @@ class ItemCreate(EventPermissionRequiredMixin, CreateView):
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('Your changes have been saved.'))
|
||||
if form.cleaned_data['copy_from']:
|
||||
form.instance.category = form.cleaned_data['copy_from'].category
|
||||
form.instance.description = form.cleaned_data['copy_from'].description
|
||||
form.instance.active = form.cleaned_data['copy_from'].active
|
||||
form.instance.available_from = form.cleaned_data['copy_from'].available_from
|
||||
form.instance.available_until = form.cleaned_data['copy_from'].available_until
|
||||
form.instance.require_voucher = form.cleaned_data['copy_from'].require_voucher
|
||||
form.instance.hide_without_voucher = form.cleaned_data['copy_from'].hide_without_voucher
|
||||
form.instance.allow_cancel = form.cleaned_data['copy_from'].allow_cancel
|
||||
|
||||
ret = super().form_valid(form)
|
||||
form.instance.log_action('pretix.event.item.added', user=self.request.user, data={
|
||||
|
||||
@@ -15,11 +15,11 @@ class MailForm(forms.Form):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['subject'] = I18nFormField(
|
||||
widget=I18nTextInput, required=True,
|
||||
langcodes=event.settings.get('locales')
|
||||
locales=event.settings.get('locales')
|
||||
)
|
||||
self.fields['message'] = I18nFormField(
|
||||
widget=I18nTextarea, required=True,
|
||||
langcodes=event.settings.get('locales'),
|
||||
locales=event.settings.get('locales'),
|
||||
help_text=_("Available placeholders: {due_date}, {event}, {order}, {order_date}, {order_url}, "
|
||||
"{invoice_name}, {invoice_company}")
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ dj-static
|
||||
csscompressor
|
||||
django-markup
|
||||
markdown
|
||||
bleach
|
||||
bleach==1.5
|
||||
raven
|
||||
django-i18nfield
|
||||
# Stripe
|
||||
|
||||
@@ -89,7 +89,7 @@ setup(
|
||||
'csscompressor',
|
||||
'django-markup',
|
||||
'markdown',
|
||||
'bleach',
|
||||
'bleach==1.5',
|
||||
'raven',
|
||||
'paypalrestsdk==1.12.*',
|
||||
'pycparser==2.13',
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
import pytz
|
||||
from i18nfield.strings import LazyI18nString
|
||||
from pytz import timezone
|
||||
from tests.base import SoupTest, extract_form_fields
|
||||
|
||||
from pretix.base.models import (
|
||||
@@ -44,7 +47,6 @@ class EventsTest(SoupTest):
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
|
||||
doc.select("[name=date_to]")[0]['value'] = "2013-12-30 17:00:00"
|
||||
doc.select("[name=settings-max_items_per_order]")[0]['value'] = "12"
|
||||
print(extract_form_fields(doc.select('.container-fluid form')[0]))
|
||||
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
|
||||
extract_form_fields(doc.select('.container-fluid form')[0]))
|
||||
@@ -52,6 +54,27 @@ class EventsTest(SoupTest):
|
||||
assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00"
|
||||
assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12"
|
||||
|
||||
def test_settings_timezone(self):
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
|
||||
doc.select("[name=date_to]")[0]['value'] = "2013-12-30 17:00:00"
|
||||
doc.select("[name=settings-max_items_per_order]")[0]['value'] = "12"
|
||||
doc.select("[name=settings-timezone]")[0]['value'] = "Asia/Tokyo"
|
||||
doc.find('option', {"value": "Asia/Tokyo"})['selected'] = 'selected'
|
||||
doc.find('option', {"value": "UTC"}).attrs.pop('selected')
|
||||
|
||||
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
|
||||
extract_form_fields(doc.select('.container-fluid form')[0]))
|
||||
assert len(doc.select(".alert-success")) > 0
|
||||
# date_to should not be changed even though the timezone is changed
|
||||
assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00"
|
||||
assert doc.find('option', {"value": "Asia/Tokyo"})['selected'] == "selected"
|
||||
assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12"
|
||||
|
||||
self.event1.refresh_from_db()
|
||||
# Asia/Tokyo -> GMT+9
|
||||
assert self.event1.date_to.strftime('%Y-%m-%d %H:%M:%S') == "2013-12-30 08:00:00"
|
||||
assert self.event1.settings.timezone == 'Asia/Tokyo'
|
||||
|
||||
def test_plugins(self):
|
||||
doc = self.get_doc('/control/event/%s/%s/settings/plugins' % (self.orga1.slug, self.event1.slug))
|
||||
self.assertIn("PayPal", doc.select(".form-plugins")[0].text)
|
||||
@@ -193,3 +216,173 @@ class EventsTest(SoupTest):
|
||||
data, follow=True)
|
||||
self.event1.settings._flush()
|
||||
assert self.event1.settings.get('ticket_download', as_type=bool)
|
||||
|
||||
def test_create_event_unauthorized(self):
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga2.pk,
|
||||
'foundation-locales': ('en', 'de')
|
||||
})
|
||||
assert doc.select(".alert-danger")
|
||||
|
||||
def test_create_invalid_default_language(self):
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga1.pk,
|
||||
'foundation-locales': ('de',)
|
||||
})
|
||||
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'basics',
|
||||
'basics-name_0': '33C3',
|
||||
'basics-name_1': '33C3',
|
||||
'basics-slug': '33c3',
|
||||
'basics-date_from': '2016-12-27 10:00:00',
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
'basics-presale_end': '2016-11-30 18:00:00',
|
||||
})
|
||||
assert doc.select(".alert-danger")
|
||||
|
||||
def test_create_duplicate_slug(self):
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga1.pk,
|
||||
'foundation-locales': ('de', 'en')
|
||||
})
|
||||
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'basics',
|
||||
'basics-name_0': '33C3',
|
||||
'basics-name_1': '33C3',
|
||||
'basics-slug': '31c3',
|
||||
'basics-date_from': '2016-12-27 10:00:00',
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
'basics-presale_end': '2016-11-30 18:00:00',
|
||||
})
|
||||
assert doc.select(".alert-danger")
|
||||
|
||||
def test_create_event_success(self):
|
||||
doc = self.get_doc('/control/events/add')
|
||||
tabletext = doc.select("form")[0].text
|
||||
self.assertIn("CCC", tabletext)
|
||||
self.assertNotIn("MRM", tabletext)
|
||||
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga1.pk,
|
||||
'foundation-locales': ('en', 'de')
|
||||
})
|
||||
assert doc.select("#id_basics-name_0")
|
||||
assert doc.select("#id_basics-name_1")
|
||||
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'basics',
|
||||
'basics-name_0': '33C3',
|
||||
'basics-name_1': '33C3',
|
||||
'basics-slug': '33c3',
|
||||
'basics-date_from': '2016-12-27 10:00:00',
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-location_1': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-01 10:00:00',
|
||||
'basics-presale_end': '2016-11-30 18:00:00',
|
||||
})
|
||||
|
||||
assert doc.select("#id_copy-copy_from_event_1")
|
||||
|
||||
self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'copy',
|
||||
'copy-copy_from_event': ''
|
||||
})
|
||||
|
||||
ev = Event.objects.get(slug='33c3')
|
||||
assert ev.name == LazyI18nString({'de': '33C3', 'en': '33C3'})
|
||||
assert ev.settings.locales == ['en', 'de']
|
||||
assert ev.settings.locale == 'en'
|
||||
assert ev.currency == 'EUR'
|
||||
assert ev.settings.timezone == 'Europe/Berlin'
|
||||
assert ev.organizer == self.orga1
|
||||
assert ev.location == LazyI18nString({'de': 'Hamburg', 'en': 'Hamburg'})
|
||||
assert EventPermission.objects.filter(event=ev, user=self.user).exists()
|
||||
|
||||
berlin_tz = timezone('Europe/Berlin')
|
||||
assert ev.date_from == berlin_tz.localize(datetime.datetime(2016, 12, 27, 10, 0, 0)).astimezone(pytz.utc)
|
||||
assert ev.date_to == berlin_tz.localize(datetime.datetime(2016, 12, 30, 19, 0, 0)).astimezone(pytz.utc)
|
||||
assert ev.presale_start == berlin_tz.localize(datetime.datetime(2016, 11, 1, 10, 0, 0)).astimezone(pytz.utc)
|
||||
assert ev.presale_end == berlin_tz.localize(datetime.datetime(2016, 11, 30, 18, 0, 0)).astimezone(pytz.utc)
|
||||
|
||||
def test_create_event_only_date_from(self):
|
||||
# date_to, presale_start & presale_end are optional fields
|
||||
self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga1.pk,
|
||||
'foundation-locales': 'en'
|
||||
})
|
||||
self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'basics',
|
||||
'basics-name_0': '33C3',
|
||||
'basics-slug': '33c3',
|
||||
'basics-date_from': '2016-12-27 10:00:00',
|
||||
'basics-date_to': '',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'UTC',
|
||||
'basics-presale_start': '',
|
||||
'basics-presale_end': '',
|
||||
})
|
||||
self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'copy',
|
||||
'copy-copy_from_event': ''
|
||||
})
|
||||
|
||||
ev = Event.objects.get(slug='33c3')
|
||||
assert ev.name == LazyI18nString({'en': '33C3'})
|
||||
assert ev.settings.locales == ['en']
|
||||
assert ev.settings.locale == 'en'
|
||||
assert ev.currency == 'EUR'
|
||||
assert ev.settings.timezone == 'UTC'
|
||||
assert ev.organizer == self.orga1
|
||||
assert ev.location == LazyI18nString({'en': 'Hamburg'})
|
||||
assert EventPermission.objects.filter(event=ev, user=self.user).exists()
|
||||
assert ev.date_from == datetime.datetime(2016, 12, 27, 10, 0, 0, tzinfo=pytz.utc)
|
||||
assert ev.date_to is None
|
||||
assert ev.presale_start is None
|
||||
assert ev.presale_end is None
|
||||
|
||||
def test_create_event_missing_date_from(self):
|
||||
# date_from is mandatory
|
||||
self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'foundation',
|
||||
'foundation-organizer': self.orga1.pk,
|
||||
'foundation-locales': 'en'
|
||||
})
|
||||
doc = self.post_doc('/control/events/add', {
|
||||
'event_wizard-current_step': 'basics',
|
||||
'basics-name_0': '33C3',
|
||||
'basics-slug': '33c3',
|
||||
'basics-date_from': '',
|
||||
'basics-date_to': '2016-12-30 19:00:00',
|
||||
'basics-location_0': 'Hamburg',
|
||||
'basics-currency': 'EUR',
|
||||
'basics-locale': 'en',
|
||||
'basics-timezone': 'Europe/Berlin',
|
||||
'basics-presale_start': '2016-11-20 11:00:00',
|
||||
'basics-presale_end': '2016-11-24 18:00:00',
|
||||
})
|
||||
assert doc.select(".alert-danger")
|
||||
|
||||
Reference in New Issue
Block a user