Compare commits

...

8 Commits

Author SHA1 Message Date
Raphael Michel
2fd81a2d20 Disable scopes for a management command 2019-06-17 10:46:10 +02:00
Raphael Michel
4271245a4a Disable scopes for get_Events_with_any_permission 2019-06-17 10:16:53 +02:00
Raphael Michel
b41139a143 Fix tests after rebase 2019-06-17 10:08:42 +02:00
Raphael Michel
a68b225529 Remove unused import 2019-06-17 10:04:54 +02:00
Raphael Michel
c12ba88ad8 Fix remaining tests 2019-06-17 10:04:54 +02:00
Raphael Michel
69a80f2540 Update tasks and cronjobs 2019-06-17 10:04:54 +02:00
Raphael Michel
867667cd12 Fix tests.api 2019-06-17 10:04:54 +02:00
Raphael Michel
5c06c41a5b Install django-scopes 2019-06-17 10:04:54 +02:00
130 changed files with 6253 additions and 4509 deletions

View File

@@ -1,4 +1,5 @@
from django.contrib.auth.models import AnonymousUser
from django_scopes import scopes_disabled
from rest_framework import exceptions
from rest_framework.authentication import TokenAuthentication
@@ -12,7 +13,8 @@ class DeviceTokenAuthentication(TokenAuthentication):
def authenticate_credentials(self, key):
model = self.get_model()
try:
device = model.objects.select_related('organizer').get(api_token=key)
with scopes_disabled():
device = model.objects.select_related('organizer').get(api_token=key)
except model.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid token.')

View File

@@ -3,7 +3,7 @@ from rest_framework.permissions import SAFE_METHODS, BasePermission
from pretix.api.models import OAuthAccessToken
from pretix.base.models import Device, Event, User
from pretix.base.models.auth import SuperuserPermissionSet
from pretix.base.models.organizer import Organizer, TeamAPIToken
from pretix.base.models.organizer import TeamAPIToken
from pretix.helpers.security import (
SessionInvalid, SessionReauthRequired, assert_session_valid,
)
@@ -50,9 +50,6 @@ class EventPermission(BasePermission):
return False
elif 'organizer' in request.resolver_match.kwargs:
request.organizer = Organizer.objects.filter(
slug=request.resolver_match.kwargs['organizer'],
).first()
if not request.organizer or not perm_holder.has_organizer_permission(request.organizer, request=request):
return False
if isinstance(perm_holder, User) and perm_holder.has_active_staff_session(request.session.session_key):

View File

@@ -4,10 +4,13 @@ from hashlib import sha1
from django.conf import settings
from django.db import transaction
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.urls import resolve
from django.utils.timezone import now
from django_scopes import scope
from rest_framework import status
from pretix.api.models import ApiCall
from pretix.base.models import Organizer
class IdempotencyMiddleware:
@@ -89,3 +92,21 @@ class IdempotencyMiddleware:
for k, v in json.loads(call.response_headers).values():
r[k] = v
return r
class ApiScopeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request: HttpRequest):
if not request.path.startswith('/api/'):
return self.get_response(request)
url = resolve(request.path_info)
if 'organizer' in url.kwargs:
request.organizer = Organizer.objects.filter(
slug=url.kwargs['organizer'],
).first()
with scope(organizer=getattr(request, 'organizer', None)):
return self.get_response(request)

View File

@@ -2,6 +2,7 @@ from datetime import timedelta
from django.dispatch import Signal, receiver
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.api.models import ApiCall, WebHookCall
from pretix.base.signals import periodic_task
@@ -17,10 +18,12 @@ instances.
@receiver(periodic_task)
@scopes_disabled()
def cleanup_webhook_logs(sender, **kwargs):
WebHookCall.objects.filter(datetime__lte=now() - timedelta(days=30)).delete()
@receiver(periodic_task)
@scopes_disabled()
def cleanup_api_logs(sender, **kwargs):
ApiCall.objects.filter(created__lte=now() - timedelta(hours=24)).delete()

View File

@@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django.utils.timezone import now
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.fields import DateTimeField
@@ -24,11 +25,11 @@ from pretix.base.services.checkin import (
)
from pretix.helpers.database import FixedOrderBy
class CheckinListFilter(FilterSet):
class Meta:
model = CheckinList
fields = ['subevent']
with scopes_disabled():
class CheckinListFilter(FilterSet):
class Meta:
model = CheckinList
fields = ['subevent']
class CheckinListViewSet(viewsets.ModelViewSet):
@@ -146,15 +147,16 @@ class CheckinListViewSet(viewsets.ModelViewSet):
return Response(response)
class CheckinOrderPositionFilter(OrderPositionFilter):
with scopes_disabled():
class CheckinOrderPositionFilter(OrderPositionFilter):
def has_checkin_qs(self, queryset, name, value):
return queryset.filter(last_checked_in__isnull=not value)
def has_checkin_qs(self, queryset, name, value):
return queryset.filter(last_checked_in__isnull=not value)
class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = CheckinListOrderPositionSerializer
queryset = OrderPosition.objects.none()
queryset = OrderPosition.all.none()
filter_backends = (DjangoFilterBackend, RichOrderingFilter)
ordering = ('attendee_name_cached', 'positionid')
ordering_fields = (

View File

@@ -3,6 +3,7 @@ from django.db import transaction
from django.db.models import ProtectedError, Q
from django.utils.timezone import now
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import filters, viewsets
from rest_framework.exceptions import PermissionDenied
@@ -18,51 +19,51 @@ from pretix.base.models import (
from pretix.base.models.event import SubEvent
from pretix.helpers.dicts import merge_dicts
with scopes_disabled():
class EventFilter(FilterSet):
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
class EventFilter(FilterSet):
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
class Meta:
model = Event
fields = ['is_public', 'live', 'has_subevents']
class Meta:
model = Event
fields = ['is_public', 'live', 'has_subevents']
def ends_after_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=value))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=value))
def ends_after_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=value))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=value))
)
)
)
return queryset.filter(expr)
def is_past_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__lt=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__lt=now()))
)
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
def is_future_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=now()))
def is_past_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__lt=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__lt=now()))
)
)
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
def is_future_qs(self, queryset, name, value):
expr = (
Q(has_subevents=False) &
Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=now()))
)
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
class EventViewSet(viewsets.ModelViewSet):
@@ -182,41 +183,42 @@ class CloneEventViewSet(viewsets.ModelViewSet):
)
class SubEventFilter(FilterSet):
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
with scopes_disabled():
class SubEventFilter(FilterSet):
is_past = django_filters.rest_framework.BooleanFilter(method='is_past_qs')
is_future = django_filters.rest_framework.BooleanFilter(method='is_future_qs')
ends_after = django_filters.rest_framework.IsoDateTimeFilter(method='ends_after_qs')
class Meta:
model = SubEvent
fields = ['active', 'event__live']
class Meta:
model = SubEvent
fields = ['active', 'event__live']
def ends_after_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=value))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=value))
)
return queryset.filter(expr)
def is_past_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__lt=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__lt=now()))
)
if value:
def ends_after_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=value))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=value))
)
return queryset.filter(expr)
else:
return queryset.exclude(expr)
def is_future_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=now()))
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
def is_past_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__lt=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__lt=now()))
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
def is_future_qs(self, queryset, name, value):
expr = Q(
Q(Q(date_to__isnull=True) & Q(date_from__gte=now()))
| Q(Q(date_to__isnull=False) & Q(date_to__gte=now()))
)
if value:
return queryset.filter(expr)
else:
return queryset.exclude(expr)
class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):

View File

@@ -3,6 +3,7 @@ from django.db.models import Q
from django.shortcuts import get_object_or_404
from django.utils.functional import cached_property
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
@@ -21,19 +22,19 @@ from pretix.base.models import (
)
from pretix.helpers.dicts import merge_dicts
with scopes_disabled():
class ItemFilter(FilterSet):
tax_rate = django_filters.CharFilter(method='tax_rate_qs')
class ItemFilter(FilterSet):
tax_rate = django_filters.CharFilter(method='tax_rate_qs')
def tax_rate_qs(self, queryset, name, value):
if value in ("0", "None", "0.00"):
return queryset.filter(Q(tax_rule__isnull=True) | Q(tax_rule__rate=0))
else:
return queryset.filter(tax_rule__rate=value)
def tax_rate_qs(self, queryset, name, value):
if value in ("0", "None", "0.00"):
return queryset.filter(Q(tax_rule__isnull=True) | Q(tax_rule__rate=0))
else:
return queryset.filter(tax_rule__rate=value)
class Meta:
model = Item
fields = ['active', 'category', 'admission', 'tax_rate', 'free_price']
class Meta:
model = Item
fields = ['active', 'category', 'admission', 'tax_rate', 'free_price']
class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
@@ -319,10 +320,11 @@ class ItemCategoryViewSet(ConditionalListView, viewsets.ModelViewSet):
super().perform_destroy(instance)
class QuestionFilter(FilterSet):
class Meta:
model = Question
fields = ['ask_during_checkin', 'required', 'identifier']
with scopes_disabled():
class QuestionFilter(FilterSet):
class Meta:
model = Question
fields = ['ask_during_checkin', 'required', 'identifier']
class QuestionViewSet(ConditionalListView, viewsets.ModelViewSet):
@@ -418,10 +420,11 @@ class QuestionOptionViewSet(viewsets.ModelViewSet):
super().perform_destroy(instance)
class QuotaFilter(FilterSet):
class Meta:
model = Quota
fields = ['subevent']
with scopes_disabled():
class QuotaFilter(FilterSet):
class Meta:
model = Quota
fields = ['subevent']
class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet):

View File

@@ -11,6 +11,7 @@ from django.shortcuts import get_object_or_404
from django.utils.timezone import make_aware, now
from django.utils.translation import ugettext as _
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import mixins, serializers, status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import (
@@ -50,17 +51,17 @@ from pretix.base.signals import (
)
from pretix.base.templatetags.money import money_filter
with scopes_disabled():
class OrderFilter(FilterSet):
email = django_filters.CharFilter(field_name='email', lookup_expr='iexact')
code = django_filters.CharFilter(field_name='code', lookup_expr='iexact')
status = django_filters.CharFilter(field_name='status', lookup_expr='iexact')
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
created_since = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='gte')
class OrderFilter(FilterSet):
email = django_filters.CharFilter(field_name='email', lookup_expr='iexact')
code = django_filters.CharFilter(field_name='code', lookup_expr='iexact')
status = django_filters.CharFilter(field_name='status', lookup_expr='iexact')
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
created_since = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='gte')
class Meta:
model = Order
fields = ['code', 'status', 'email', 'locale', 'testmode', 'require_approval']
class Meta:
model = Order
fields = ['code', 'status', 'email', 'locale', 'testmode', 'require_approval']
class OrderViewSet(viewsets.ModelViewSet):
@@ -531,48 +532,49 @@ class OrderViewSet(viewsets.ModelViewSet):
self.get_object().gracefully_delete(user=self.request.user if self.request.user.is_authenticated else None, auth=self.request.auth)
class OrderPositionFilter(FilterSet):
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
has_checkin = django_filters.rest_framework.BooleanFilter(method='has_checkin_qs')
attendee_name = django_filters.CharFilter(method='attendee_name_qs')
search = django_filters.CharFilter(method='search_qs')
with scopes_disabled():
class OrderPositionFilter(FilterSet):
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
has_checkin = django_filters.rest_framework.BooleanFilter(method='has_checkin_qs')
attendee_name = django_filters.CharFilter(method='attendee_name_qs')
search = django_filters.CharFilter(method='search_qs')
def search_qs(self, queryset, name, value):
return queryset.filter(
Q(secret__istartswith=value)
| Q(attendee_name_cached__icontains=value)
| Q(addon_to__attendee_name_cached__icontains=value)
| Q(attendee_email__icontains=value)
| Q(addon_to__attendee_email__icontains=value)
| Q(order__code__istartswith=value)
| Q(order__invoice_address__name_cached__icontains=value)
| Q(order__email__icontains=value)
)
def search_qs(self, queryset, name, value):
return queryset.filter(
Q(secret__istartswith=value)
| Q(attendee_name_cached__icontains=value)
| Q(addon_to__attendee_name_cached__icontains=value)
| Q(attendee_email__icontains=value)
| Q(addon_to__attendee_email__icontains=value)
| Q(order__code__istartswith=value)
| Q(order__invoice_address__name_cached__icontains=value)
| Q(order__email__icontains=value)
)
def has_checkin_qs(self, queryset, name, value):
return queryset.filter(checkins__isnull=not value)
def has_checkin_qs(self, queryset, name, value):
return queryset.filter(checkins__isnull=not value)
def attendee_name_qs(self, queryset, name, value):
return queryset.filter(Q(attendee_name_cached__iexact=value) | Q(addon_to__attendee_name_cached__iexact=value))
def attendee_name_qs(self, queryset, name, value):
return queryset.filter(Q(attendee_name_cached__iexact=value) | Q(addon_to__attendee_name_cached__iexact=value))
class Meta:
model = OrderPosition
fields = {
'item': ['exact', 'in'],
'variation': ['exact', 'in'],
'secret': ['exact'],
'order__status': ['exact', 'in'],
'addon_to': ['exact', 'in'],
'subevent': ['exact', 'in'],
'pseudonymization_id': ['exact'],
'voucher__code': ['exact'],
'voucher': ['exact'],
}
class Meta:
model = OrderPosition
fields = {
'item': ['exact', 'in'],
'variation': ['exact', 'in'],
'secret': ['exact'],
'order__status': ['exact', 'in'],
'addon_to': ['exact', 'in'],
'subevent': ['exact', 'in'],
'pseudonymization_id': ['exact'],
'voucher__code': ['exact'],
'voucher': ['exact'],
}
class OrderPositionViewSet(mixins.DestroyModelMixin, viewsets.ReadOnlyModelViewSet):
serializer_class = OrderPositionSerializer
queryset = OrderPosition.objects.none()
queryset = OrderPosition.all.none()
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('order__datetime', 'positionid')
ordering_fields = ('order__code', 'order__datetime', 'positionid', 'attendee_name', 'order__status',)
@@ -960,22 +962,23 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
serializer.save()
class InvoiceFilter(FilterSet):
refers = django_filters.CharFilter(method='refers_qs')
number = django_filters.CharFilter(method='nr_qs')
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
with scopes_disabled():
class InvoiceFilter(FilterSet):
refers = django_filters.CharFilter(method='refers_qs')
number = django_filters.CharFilter(method='nr_qs')
order = django_filters.CharFilter(field_name='order', lookup_expr='code__iexact')
def refers_qs(self, queryset, name, value):
return queryset.annotate(
refers_nr=Concat('refers__prefix', 'refers__invoice_no')
).filter(refers_nr__iexact=value)
def refers_qs(self, queryset, name, value):
return queryset.annotate(
refers_nr=Concat('refers__prefix', 'refers__invoice_no')
).filter(refers_nr__iexact=value)
def nr_qs(self, queryset, name, value):
return queryset.filter(nr__iexact=value)
def nr_qs(self, queryset, name, value):
return queryset.filter(nr__iexact=value)
class Meta:
model = Invoice
fields = ['order', 'number', 'is_cancellation', 'refers', 'locale']
class Meta:
model = Invoice
fields = ['order', 'number', 'is_cancellation', 'refers', 'locale']
class RetryException(APIException):

View File

@@ -6,6 +6,7 @@ from django.utils.timezone import now
from django_filters.rest_framework import (
BooleanFilter, DjangoFilterBackend, FilterSet,
)
from django_scopes import scopes_disabled
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
@@ -15,22 +16,22 @@ from rest_framework.response import Response
from pretix.api.serializers.voucher import VoucherSerializer
from pretix.base.models import Voucher
with scopes_disabled():
class VoucherFilter(FilterSet):
active = BooleanFilter(method='filter_active')
class VoucherFilter(FilterSet):
active = BooleanFilter(method='filter_active')
class Meta:
model = Voucher
fields = ['code', 'max_usages', 'redeemed', 'block_quota', 'allow_ignore_quota',
'price_mode', 'value', 'item', 'variation', 'quota', 'tag', 'subevent']
class Meta:
model = Voucher
fields = ['code', 'max_usages', 'redeemed', 'block_quota', 'allow_ignore_quota',
'price_mode', 'value', 'item', 'variation', 'quota', 'tag', 'subevent']
def filter_active(self, queryset, name, value):
if value:
return queryset.filter(Q(redeemed__lt=F('max_usages')) &
(Q(valid_until__isnull=True) | Q(valid_until__gt=now())))
else:
return queryset.filter(Q(redeemed__gte=F('max_usages')) |
(Q(valid_until__isnull=False) & Q(valid_until__lte=now())))
def filter_active(self, queryset, name, value):
if value:
return queryset.filter(Q(redeemed__lt=F('max_usages')) &
(Q(valid_until__isnull=True) | Q(valid_until__gt=now())))
else:
return queryset.filter(Q(redeemed__gte=F('max_usages')) |
(Q(valid_until__isnull=False) & Q(valid_until__lte=now())))
class VoucherViewSet(viewsets.ModelViewSet):

View File

@@ -1,5 +1,6 @@
import django_filters
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
from django_scopes import scopes_disabled
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied, ValidationError
@@ -10,16 +11,16 @@ from pretix.api.serializers.waitinglist import WaitingListSerializer
from pretix.base.models import WaitingListEntry
from pretix.base.models.waitinglist import WaitingListException
with scopes_disabled():
class WaitingListFilter(FilterSet):
has_voucher = django_filters.rest_framework.BooleanFilter(method='has_voucher_qs')
class WaitingListFilter(FilterSet):
has_voucher = django_filters.rest_framework.BooleanFilter(method='has_voucher_qs')
def has_voucher_qs(self, queryset, name, value):
return queryset.filter(voucher__isnull=not value)
def has_voucher_qs(self, queryset, name, value):
return queryset.filter(voucher__isnull=not value)
class Meta:
model = WaitingListEntry
fields = ['item', 'variation', 'email', 'locale', 'has_voucher', 'subevent']
class Meta:
model = WaitingListEntry
fields = ['item', 'variation', 'email', 'locale', 'has_voucher', 'subevent']
class WaitingListViewSet(viewsets.ModelViewSet):

View File

@@ -8,6 +8,7 @@ from celery.exceptions import MaxRetriesExceededError
from django.db.models import Exists, OuterRef, Q
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
from django_scopes import scope, scopes_disabled
from requests import RequestException
from pretix.api.models import WebHook, WebHookCall, WebHookEventListener
@@ -203,51 +204,52 @@ def notify_webhooks(logentry_id: int):
@app.task(base=ProfiledTask, bind=True, max_retries=9)
def send_webhook(self, logentry_id: int, action_type: str, webhook_id: int):
# 9 retries with 2**(2*x) timing is roughly 72 hours
logentry = LogEntry.all.get(id=logentry_id)
webhook = WebHook.objects.get(id=webhook_id)
with scopes_disabled():
webhook = WebHook.objects.get(id=webhook_id)
with scope(organizer=webhook.organizer):
logentry = LogEntry.all.get(id=logentry_id)
types = get_all_webhook_events()
event_type = types.get(action_type)
if not event_type or not webhook.enabled:
return # Ignore, e.g. plugin not installed
types = get_all_webhook_events()
event_type = types.get(action_type)
if not event_type or not webhook.enabled:
return # Ignore, e.g. plugin not installed
payload = event_type.build_payload(logentry)
t = time.time()
payload = event_type.build_payload(logentry)
t = time.time()
try:
try:
resp = requests.post(
webhook.target_url,
json=payload,
allow_redirects=False
)
WebHookCall.objects.create(
webhook=webhook,
action_type=logentry.action_type,
target_url=webhook.target_url,
is_retry=self.request.retries > 0,
execution_time=time.time() - t,
return_code=resp.status_code,
payload=json.dumps(payload),
response_body=resp.text[:1024 * 1024],
success=200 <= resp.status_code <= 299
)
if resp.status_code == 410:
webhook.enabled = False
webhook.save()
elif resp.status_code > 299:
try:
resp = requests.post(
webhook.target_url,
json=payload,
allow_redirects=False
)
WebHookCall.objects.create(
webhook=webhook,
action_type=logentry.action_type,
target_url=webhook.target_url,
is_retry=self.request.retries > 0,
execution_time=time.time() - t,
return_code=resp.status_code,
payload=json.dumps(payload),
response_body=resp.text[:1024 * 1024],
success=200 <= resp.status_code <= 299
)
if resp.status_code == 410:
webhook.enabled = False
webhook.save()
elif resp.status_code > 299:
raise self.retry(countdown=2 ** (self.request.retries * 2))
except RequestException as e:
WebHookCall.objects.create(
webhook=webhook,
action_type=logentry.action_type,
target_url=webhook.target_url,
is_retry=self.request.retries > 0,
execution_time=time.time() - t,
return_code=0,
payload=json.dumps(payload),
response_body=str(e)[:1024 * 1024]
)
raise self.retry(countdown=2 ** (self.request.retries * 2))
except RequestException as e:
WebHookCall.objects.create(
webhook=webhook,
action_type=logentry.action_type,
target_url=webhook.target_url,
is_retry=self.request.retries > 0,
execution_time=time.time() - t,
return_code=0,
payload=json.dumps(payload),
response_body=str(e)[:1024 * 1024]
)
raise self.retry(countdown=2 ** (self.request.retries * 2))
except MaxRetriesExceededError:
pass
except MaxRetriesExceededError:
pass

View File

@@ -12,6 +12,7 @@ from django.utils.crypto import get_random_string
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django_otp.models import Device
from django_scopes import scopes_disabled
from pretix.base.i18n import language
from pretix.helpers.urls import build_absolute_uri
@@ -283,6 +284,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
return True
return False
@scopes_disabled()
def get_events_with_any_permission(self, request=None):
"""
Returns a queryset of events the user has any permissions to.
@@ -300,6 +302,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
| Q(id__in=self.teams.values_list('limit_events__id', flat=True))
)
@scopes_disabled()
def get_events_with_permission(self, permission, request=None):
"""
Returns a queryset of events the user has a specific permissions to.

View File

@@ -3,6 +3,7 @@ from django.db.models import Case, Count, F, OuterRef, Q, Subquery, When
from django.db.models.functions import Coalesce
from django.utils.timezone import now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_scopes import ScopedManager
from pretix.base.models import LoggedModel
@@ -20,6 +21,8 @@ class CheckinList(LoggedModel):
'order have not been paid. This only works with pretixdesk '
'0.3.0 or newer or pretixdroid 1.9 or newer.'))
objects = ScopedManager(organizer='event__organizer')
class Meta:
ordering = ('subevent__date_from', 'name')
@@ -167,6 +170,8 @@ class Checkin(models.Model):
'pretixbase.CheckinList', related_name='checkins', on_delete=models.PROTECT,
)
objects = ScopedManager(organizer='position__order__event__organizer')
class Meta:
unique_together = (('list', 'position'),)

View File

@@ -4,6 +4,7 @@ from django.db import models
from django.db.models import Max
from django.utils.crypto import get_random_string
from django.utils.translation import ugettext_lazy as _
from django_scopes import ScopedManager
from pretix.base.models import LoggedModel
@@ -71,6 +72,8 @@ class Device(LoggedModel):
null=True, blank=True
)
objects = ScopedManager(organizer='organizer')
class Meta:
unique_together = (('organizer', 'device_id'),)

View File

@@ -17,6 +17,7 @@ from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.timezone import make_aware, now
from django.utils.translation import ugettext_lazy as _
from django_scopes import ScopedManager
from i18nfield.fields import I18nCharField, I18nTextField
from pretix.base.models.base import LoggedModel
@@ -336,6 +337,8 @@ class Event(EventMixin, LoggedModel):
default=False
)
objects = ScopedManager(organizer='organizer')
class Meta:
verbose_name = _("Event")
verbose_name_plural = _("Events")
@@ -875,6 +878,8 @@ class SubEvent(EventMixin, LoggedModel):
items = models.ManyToManyField('Item', through='SubEventItem')
variations = models.ManyToManyField('ItemVariation', through='SubEventItemVariation')
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Date in event series")
verbose_name_plural = _("Dates in event series")

View File

@@ -9,6 +9,7 @@ from django.utils.crypto import get_random_string
from django.utils.functional import cached_property
from django.utils.translation import pgettext
from django_countries.fields import CountryField
from django_scopes import ScopedManager
def invoice_filename(instance, filename: str) -> str:
@@ -107,6 +108,8 @@ class Invoice(models.Model):
file = models.FileField(null=True, blank=True, upload_to=invoice_filename, max_length=255)
internal_reference = models.TextField(blank=True)
objects = ScopedManager(organizer='event__organizer')
@staticmethod
def _to_numeric_invoice_number(number):
return '{:05d}'.format(int(number))

View File

@@ -17,6 +17,7 @@ from django.utils.functional import cached_property
from django.utils.timezone import is_naive, make_aware, now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_countries.fields import Country
from django_scopes import ScopedManager
from i18nfield.fields import I18nCharField, I18nTextField
from pretix.base.models import fields
@@ -155,28 +156,41 @@ class SubEventItemVariation(models.Model):
self.subevent.event.cache.clear()
def filter_available(qs, channel='web', voucher=None, allow_addons=False):
q = (
# IMPORTANT: If this is updated, also update the ItemVariation query
# in models/event.py: EventMixin.annotated()
Q(active=True)
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
& Q(sales_channels__contains=channel) & Q(require_bundling=False)
)
if not allow_addons:
q &= Q(Q(category__isnull=True) | Q(category__is_addon=False))
qs = qs.filter(q)
vouchq = Q(hide_without_voucher=False)
if voucher:
if voucher.item_id:
vouchq |= Q(pk=voucher.item_id)
qs = qs.filter(pk=voucher.item_id)
elif voucher.quota_id:
qs = qs.filter(quotas__in=[voucher.quota_id])
return qs.filter(vouchq)
class ItemQuerySet(models.QuerySet):
def filter_available(self, channel='web', voucher=None, allow_addons=False):
q = (
# IMPORTANT: If this is updated, also update the ItemVariation query
# in models/event.py: EventMixin.annotated()
Q(active=True)
& Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
& Q(sales_channels__contains=channel) & Q(require_bundling=False)
)
if not allow_addons:
q &= Q(Q(category__isnull=True) | Q(category__is_addon=False))
qs = self.filter(q)
return filter_available(self, channel, voucher, allow_addons)
vouchq = Q(hide_without_voucher=False)
if voucher:
if voucher.item_id:
vouchq |= Q(pk=voucher.item_id)
qs = qs.filter(pk=voucher.item_id)
elif voucher.quota_id:
qs = qs.filter(quotas__in=[voucher.quota_id])
return qs.filter(vouchq)
class ItemQuerySetManager(ScopedManager(organizer='event__organizer').__class__):
def __init__(self):
super().__init__()
self._queryset_class = ItemQuerySet
def filter_available(self, channel='web', voucher=None, allow_addons=False):
return filter_available(self.get_queryset(), channel, voucher, allow_addons)
class Item(LoggedModel):
@@ -226,7 +240,7 @@ class Item(LoggedModel):
:type sales_channels: bool
"""
objects = ItemQuerySet.as_manager()
objects = ItemQuerySetManager()
event = models.ForeignKey(
Event,
@@ -591,6 +605,8 @@ class ItemVariation(models.Model):
'discounted one. This is just a cosmetic setting and will not actually impact pricing.')
)
objects = ScopedManager(organizer='item__event__organizer')
class Meta:
verbose_name = _("Product variation")
verbose_name_plural = _("Product variations")
@@ -985,6 +1001,8 @@ class Question(LoggedModel):
)
dependency_value = models.TextField(null=True, blank=True)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Question")
verbose_name_plural = _("Questions")
@@ -1234,6 +1252,8 @@ class Quota(LoggedModel):
cached_availability_paid_orders = models.PositiveIntegerField(null=True, blank=True)
cached_availability_time = models.DateTimeField(null=True, blank=True)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Quota")
verbose_name_plural = _("Quotas")

View File

@@ -26,6 +26,7 @@ from django.utils.functional import cached_property
from django.utils.timezone import make_aware, now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_countries.fields import Country, CountryField
from django_scopes import ScopedManager, scopes_disabled
from i18nfield.strings import LazyI18nString
from jsonfallback.fields import FallbackJSONField
@@ -186,6 +187,8 @@ class Order(LockModel, LoggedModel):
verbose_name=_('E-mail address verified')
)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Order")
verbose_name_plural = _("Orders")
@@ -231,6 +234,7 @@ class Order(LockModel, LoggedModel):
return self.all_fees(manager='objects')
@cached_property
@scopes_disabled()
def count_positions(self):
if hasattr(self, 'pcnt'):
return self.pcnt or 0
@@ -254,6 +258,7 @@ class Order(LockModel, LoggedModel):
return None
@property
@scopes_disabled()
def payment_refund_sum(self):
payment_sum = self.payments.filter(
state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED)
@@ -265,6 +270,7 @@ class Order(LockModel, LoggedModel):
return payment_sum - refund_sum
@property
@scopes_disabled()
def pending_sum(self):
total = self.total
if self.status == Order.STATUS_CANCELED:
@@ -439,6 +445,7 @@ class Order(LockModel, LoggedModel):
return round_decimal(fee, self.event.currency)
@property
@scopes_disabled()
def user_cancel_allowed(self) -> bool:
"""
Returns whether or not this order can be canceled by the user.
@@ -822,6 +829,8 @@ class QuestionAnswer(models.Model):
max_length=255
)
objects = ScopedManager(organizer='question__event__organizer')
@property
def backend_file_url(self):
if self.file:
@@ -1145,6 +1154,8 @@ class OrderPayment(models.Model):
)
migrated = models.BooleanField(default=False)
objects = ScopedManager(organizer='order__event__organizer')
class Meta:
ordering = ('local_id',)
@@ -1501,6 +1512,8 @@ class OrderRefund(models.Model):
null=True, blank=True
)
objects = ScopedManager(organizer='order__event__organizer')
class Meta:
ordering = ('local_id',)
@@ -1562,7 +1575,7 @@ class OrderRefund(models.Model):
super().save(*args, **kwargs)
class ActivePositionManager(models.Manager):
class ActivePositionManager(ScopedManager(organizer='order__event__organizer').__class__):
def get_queryset(self):
return super().get_queryset().filter(canceled=False)
@@ -1639,7 +1652,7 @@ class OrderFee(models.Model):
)
canceled = models.BooleanField(default=False)
all = models.Manager()
all = ScopedManager(organizer='order__event__organizer')
objects = ActivePositionManager()
@property
@@ -1744,7 +1757,7 @@ class OrderPosition(AbstractPosition):
)
canceled = models.BooleanField(default=False)
all = models.Manager()
all = ScopedManager(organizer='order__event__organizer')
objects = ActivePositionManager()
class Meta:
@@ -1951,6 +1964,8 @@ class CartPosition(AbstractPosition):
)
is_bundled = models.BooleanField(default=False)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Cart position")
verbose_name_plural = _("Cart positions")
@@ -2000,6 +2015,8 @@ class InvoiceAddress(models.Model):
blank=True
)
objects = ScopedManager(organizer='order__event__organizer')
def save(self, **kwargs):
if self.order:
self.order.touch()

View File

@@ -8,6 +8,7 @@ from django.db.models import Q
from django.utils.crypto import get_random_string
from django.utils.timezone import now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_scopes import ScopedManager
from ..decimal import round_decimal
from .base import LoggedModel
@@ -173,6 +174,8 @@ class Voucher(LoggedModel):
"convenience.")
)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Voucher")
verbose_name_plural = _("Vouchers")

View File

@@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.utils.timezone import now
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_scopes import ScopedManager
from pretix.base.i18n import language
from pretix.base.models import Voucher
@@ -67,6 +68,8 @@ class WaitingListEntry(LoggedModel):
)
priority = models.IntegerField(default=0)
objects = ScopedManager(organizer='event__organizer')
class Meta:
verbose_name = _("Waiting list entry")
verbose_name_plural = _("Waiting list entries")

View File

@@ -10,6 +10,7 @@ from django.db.models import Q
from django.dispatch import receiver
from django.utils.timezone import make_aware, now
from django.utils.translation import pgettext_lazy, ugettext as _
from django_scopes import scopes_disabled
from pretix.base.i18n import language
from pretix.base.models import (
@@ -23,7 +24,7 @@ from pretix.base.reldate import RelativeDateWrapper
from pretix.base.services.checkin import _save_answers
from pretix.base.services.locking import LockTimeoutException, NoLockManager
from pretix.base.services.pricing import get_price
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.base.templatetags.rich_text import rich_text
from pretix.celery_app import app
@@ -902,7 +903,7 @@ def get_fees(event, request, total, invoice_address, provider):
return fees
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def add_items_to_cart(self, event: int, items: List[dict], cart_id: str=None, locale='en',
invoice_address: int=None, widget_data=None, sales_channel='web') -> None:
"""
@@ -913,12 +914,11 @@ def add_items_to_cart(self, event: int, items: List[dict], cart_id: str=None, lo
:raises CartError: On any error that occured
"""
with language(locale):
event = Event.objects.get(id=event)
ia = False
if invoice_address:
try:
ia = InvoiceAddress.objects.get(pk=invoice_address)
with scopes_disabled():
ia = InvoiceAddress.objects.get(pk=invoice_address)
except InvoiceAddress.DoesNotExist:
pass
@@ -934,8 +934,8 @@ def add_items_to_cart(self, event: int, items: List[dict], cart_id: str=None, lo
raise CartError(error_messages['busy'])
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def remove_cart_position(self, event: int, position: int, cart_id: str=None, locale='en') -> None:
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def remove_cart_position(self, event: Event, position: int, cart_id: str=None, locale='en') -> None:
"""
Removes a list of items from a user's cart.
:param event: The event ID in question
@@ -943,7 +943,6 @@ def remove_cart_position(self, event: int, position: int, cart_id: str=None, loc
:param session: Session ID of a guest
"""
with language(locale):
event = Event.objects.get(id=event)
try:
try:
cm = CartManager(event=event, cart_id=cart_id)
@@ -955,15 +954,14 @@ def remove_cart_position(self, event: int, position: int, cart_id: str=None, loc
raise CartError(error_messages['busy'])
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def clear_cart(self, event: int, cart_id: str=None, locale='en') -> None:
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def clear_cart(self, event: Event, cart_id: str=None, locale='en') -> None:
"""
Removes a list of items from a user's cart.
:param event: The event ID in question
:param session: Session ID of a guest
"""
with language(locale):
event = Event.objects.get(id=event)
try:
try:
cm = CartManager(event=event, cart_id=cart_id)
@@ -975,8 +973,8 @@ def clear_cart(self, event: int, cart_id: str=None, locale='en') -> None:
raise CartError(error_messages['busy'])
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def set_cart_addons(self, event: int, addons: List[dict], cart_id: str=None, locale='en',
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(CartError,))
def set_cart_addons(self, event: Event, addons: List[dict], cart_id: str=None, locale='en',
invoice_address: int=None, sales_channel='web') -> None:
"""
Removes a list of items from a user's cart.
@@ -985,12 +983,11 @@ def set_cart_addons(self, event: int, addons: List[dict], cart_id: str=None, loc
:param session: Session ID of a guest
"""
with language(locale):
event = Event.objects.get(id=event)
ia = False
if invoice_address:
try:
ia = InvoiceAddress.objects.get(pk=invoice_address)
with scopes_disabled():
ia = InvoiceAddress.objects.get(pk=invoice_address)
except InvoiceAddress.DoesNotExist:
pass
try:

View File

@@ -2,6 +2,7 @@ from datetime import timedelta
from django.dispatch import receiver
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import CachedCombinedTicket, CachedTicket
@@ -10,6 +11,7 @@ from ..signals import periodic_task
@receiver(signal=periodic_task)
@scopes_disabled()
def clean_cart_positions(sender, **kwargs):
for cp in CartPosition.objects.filter(expires__lt=now() - timedelta(days=14), addon_to__isnull=False):
cp.delete()
@@ -20,12 +22,14 @@ def clean_cart_positions(sender, **kwargs):
@receiver(signal=periodic_task)
@scopes_disabled()
def clean_cached_files(sender, **kwargs):
for cf in CachedFile.objects.filter(expires__isnull=False, expires__lt=now()):
cf.delete()
@receiver(signal=periodic_task)
@scopes_disabled()
def clean_cached_tickets(sender, **kwargs):
for cf in CachedTicket.objects.filter(created__lte=now() - timedelta(days=30)):
cf.delete()

View File

@@ -6,7 +6,7 @@ from django.utils.translation import ugettext
from pretix.base.i18n import LazyLocaleException, language
from pretix.base.models import CachedFile, Event, cachedfile_name
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask
from pretix.base.signals import register_data_exporters
from pretix.celery_app import app
@@ -15,9 +15,8 @@ class ExportError(LazyLocaleException):
pass
@app.task(base=ProfiledTask, throws=(ExportError,))
def export(event: str, fileid: str, provider: str, form_data: Dict[str, Any]) -> None:
event = Event.objects.get(id=event)
@app.task(base=ProfiledEventTask, throws=(ExportError,))
def export(event: Event, fileid: str, provider: str, form_data: Dict[str, Any]) -> None:
file = CachedFile.objects.get(id=fileid)
with language(event.settings.locale), override(event.settings.timezone):
responses = register_data_exporters.send(event)

View File

@@ -15,6 +15,7 @@ from django.utils import timezone
from django.utils.timezone import now
from django.utils.translation import pgettext, ugettext as _
from django_countries.fields import Country
from django_scopes import scope, scopes_disabled
from i18nfield.strings import LazyI18nString
from pretix.base.i18n import language
@@ -244,16 +245,18 @@ def generate_invoice(order: Order, trigger_pdf=True):
@app.task(base=TransactionAwareTask)
def invoice_pdf_task(invoice: int):
i = Invoice.objects.get(pk=invoice)
if i.shredded:
return None
if i.file:
i.file.delete()
with language(i.locale):
fname, ftype, fcontent = i.event.invoice_renderer.generate(i)
i.file.save(fname, ContentFile(fcontent))
i.save()
return i.file.name
with scopes_disabled():
i = Invoice.objects.get(pk=invoice)
with scope(organizer=i.order.event.organizer):
if i.shredded:
return None
if i.file:
i.file.delete()
with language(i.locale):
fname, ftype, fcontent = i.event.invoice_renderer.generate(i)
i.file.save(fname, ContentFile(fcontent))
i.save()
return i.file.name
def invoice_qualified(order: Order):

View File

@@ -10,6 +10,7 @@ from django.conf import settings
from django.core.mail import EmailMultiAlternatives, get_connection
from django.template.loader import get_template
from django.utils.translation import ugettext as _
from django_scopes import scope, scopes_disabled
from i18nfield.strings import LazyI18nString
from pretix.base.email import ClassicMailRenderer
@@ -234,83 +235,87 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
pass
if event:
event = Event.objects.get(id=event)
with scopes_disabled():
event = Event.objects.get(id=event)
backend = event.get_mail_backend()
cm = lambda: scope(organizer=event.organizer) # noqa
else:
backend = get_connection(fail_silently=False)
cm = lambda: scopes_disabled() # noqa
if event:
if order:
try:
order = event.orders.get(pk=order)
except Order.DoesNotExist:
order = None
else:
if position:
try:
position = order.positions.get(pk=position)
except OrderPosition.DoesNotExist:
attach_tickets = False
if attach_tickets:
args = []
attach_size = 0
for name, ct in get_tickets_for_order(order, base_position=position):
content = ct.file.read()
args.append((name, content, ct.type))
attach_size += len(content)
with cm():
if event:
if order:
try:
order = event.orders.get(pk=order)
except Order.DoesNotExist:
order = None
else:
if position:
try:
position = order.positions.get(pk=position)
except OrderPosition.DoesNotExist:
attach_tickets = False
if attach_tickets:
args = []
attach_size = 0
for name, ct in get_tickets_for_order(order, base_position=position):
content = ct.file.read()
args.append((name, content, ct.type))
attach_size += len(content)
if attach_size < 4 * 1024 * 1024:
# Do not attach more than 4MB, it will bounce way to often.
for a in args:
try:
email.attach(*a)
except:
pass
else:
order.log_action(
'pretix.event.order.email.attachments.skipped',
data={
'subject': 'Attachments skipped',
'message': 'Attachment have not been send because {} bytes are likely too large to arrive.'.format(attach_size),
'recipient': '',
'invoices': [],
}
)
if attach_size < 4 * 1024 * 1024:
# Do not attach more than 4MB, it will bounce way to often.
for a in args:
try:
email.attach(*a)
except:
pass
else:
order.log_action(
'pretix.event.order.email.attachments.skipped',
data={
'subject': 'Attachments skipped',
'message': 'Attachment have not been send because {} bytes are likely too large to arrive.'.format(attach_size),
'recipient': '',
'invoices': [],
}
)
email = email_filter.send_chained(event, 'message', message=email, order=order)
email = email_filter.send_chained(event, 'message', message=email, order=order)
try:
backend.send_messages([email])
except smtplib.SMTPResponseException as e:
if e.smtp_code in (101, 111, 421, 422, 431, 442, 447, 452):
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 2))
logger.exception('Error sending email')
try:
backend.send_messages([email])
except smtplib.SMTPResponseException as e:
if e.smtp_code in (101, 111, 421, 422, 431, 442, 447, 452):
self.retry(max_retries=5, countdown=2 ** (self.request.retries * 2))
logger.exception('Error sending email')
if order:
order.log_action(
'pretix.event.order.email.error',
data={
'subject': 'SMTP code {}'.format(e.smtp_code),
'message': e.smtp_error.decode() if isinstance(e.smtp_error, bytes) else str(e.smtp_error),
'recipient': '',
'invoices': [],
}
)
if order:
order.log_action(
'pretix.event.order.email.error',
data={
'subject': 'SMTP code {}'.format(e.smtp_code),
'message': e.smtp_error.decode() if isinstance(e.smtp_error, bytes) else str(e.smtp_error),
'recipient': '',
'invoices': [],
}
)
raise SendMailException('Failed to send an email to {}.'.format(to))
except Exception as e:
if order:
order.log_action(
'pretix.event.order.email.error',
data={
'subject': 'Internal error',
'message': str(e),
'recipient': '',
'invoices': [],
}
)
logger.exception('Error sending email')
raise SendMailException('Failed to send an email to {}.'.format(to))
raise SendMailException('Failed to send an email to {}.'.format(to))
except Exception as e:
if order:
order.log_action(
'pretix.event.order.email.error',
data={
'subject': 'Internal error',
'message': str(e),
'recipient': '',
'invoices': [],
}
)
logger.exception('Error sending email')
raise SendMailException('Failed to send an email to {}.'.format(to))
def mail_send(*args, **kwargs):

View File

@@ -1,5 +1,6 @@
from django.conf import settings
from django.template.loader import get_template
from django_scopes import scope, scopes_disabled
from inlinestyler.utils import inline_css
from pretix.base.i18n import language
@@ -12,6 +13,7 @@ from pretix.helpers.urls import build_absolute_uri
@app.task(base=TransactionAwareTask)
@scopes_disabled()
def notify(logentry_id: int):
logentry = LogEntry.all.get(id=logentry_id)
if not logentry.event:
@@ -66,17 +68,22 @@ def notify(logentry_id: int):
@app.task(base=ProfiledTask)
def send_notification(logentry_id: int, action_type: str, user_id: int, method: str):
logentry = LogEntry.all.get(id=logentry_id)
user = User.objects.get(id=user_id)
types = get_all_notification_types(logentry.event)
notification_type = types.get(action_type)
if not notification_type:
return # Ignore, e.g. plugin not active for this event
if logentry.event:
sm = lambda: scope(organizer=logentry.event.organizer) # noqa
else:
sm = lambda: scopes_disabled() # noqa
with sm():
user = User.objects.get(id=user_id)
types = get_all_notification_types(logentry.event)
notification_type = types.get(action_type)
if not notification_type:
return # Ignore, e.g. plugin not active for this event
with language(user.locale):
notification = notification_type.build_notification(logentry)
with language(user.locale):
notification = notification_type.build_notification(logentry)
if method == "mail":
send_notification_mail(notification, user)
if method == "mail":
send_notification_mail(notification, user)
def send_notification_mail(notification: Notification, user: User):

View File

@@ -16,6 +16,7 @@ from django.utils.formats import date_format
from django.utils.functional import cached_property
from django.utils.timezone import make_aware, now
from django.utils.translation import ugettext as _
from django_scopes import scopes_disabled
from pretix.api.models import OAuthApplication
from pretix.base.i18n import (
@@ -42,7 +43,7 @@ from pretix.base.services.invoices import (
from pretix.base.services.locking import LockTimeoutException, NoLockManager
from pretix.base.services.mail import SendMailException
from pretix.base.services.pricing import get_price
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask, ProfiledTask
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.base.signals import (
allow_ticket_download, order_approved, order_canceled, order_changed,
@@ -715,10 +716,8 @@ def _order_placed_email_attendee(event: Event, order: Order, position: OrderPosi
logger.exception('Order received email could not be sent to attendee')
def _perform_order(event: str, payment_provider: str, position_ids: List[str],
def _perform_order(event: Event, payment_provider: str, position_ids: List[str],
email: str, locale: str, address: int, meta_info: dict=None, sales_channel: str='web'):
event = Event.objects.get(id=event)
if payment_provider:
pprov = event.get_payment_providers().get(payment_provider)
if not pprov:
@@ -732,7 +731,8 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
addr = None
if address is not None:
try:
addr = InvoiceAddress.objects.get(pk=address)
with scopes_disabled():
addr = InvoiceAddress.objects.get(pk=address)
except InvoiceAddress.DoesNotExist:
pass
@@ -804,6 +804,7 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
@receiver(signal=periodic_task)
@scopes_disabled()
def expire_orders(sender, **kwargs):
eventcache = {}
@@ -818,6 +819,7 @@ def expire_orders(sender, **kwargs):
@receiver(signal=periodic_task)
@scopes_disabled()
def send_expiry_warnings(sender, **kwargs):
eventcache = {}
today = now().replace(hour=0, minute=0, second=0)
@@ -875,6 +877,7 @@ def send_expiry_warnings(sender, **kwargs):
@receiver(signal=periodic_task)
@scopes_disabled()
def send_download_reminders(sender, **kwargs):
today = now().replace(hour=0, minute=0, second=0, microsecond=0)
@@ -1497,8 +1500,8 @@ class OrderChangeManager:
return pprov
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
def perform_order(self, event: str, payment_provider: str, positions: List[str],
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
def perform_order(self, event: Event, payment_provider: str, positions: List[str],
email: str=None, locale: str=None, address: int=None, meta_info: dict=None,
sales_channel: str='web'):
with language(locale):
@@ -1513,6 +1516,7 @@ def perform_order(self, event: str, payment_provider: str, positions: List[str],
@app.task(base=ProfiledTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
@scopes_disabled()
def cancel_order(self, order: int, user: int=None, send_mail: bool=True, api_token=None, oauth_application=None,
device=None, cancellation_fee=None, try_auto_refund=False):
try:

View File

@@ -4,6 +4,7 @@ from django.conf import settings
from django.db.models import Max, Q
from django.dispatch import receiver
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import Event, LogEntry
from pretix.celery_app import app
@@ -17,6 +18,7 @@ def build_all_quota_caches(sender, **kwargs):
@app.task
@scopes_disabled()
def refresh_quota_caches():
# Active events
active = LogEntry.objects.using(settings.DATABASE_REPLICA).filter(

View File

@@ -11,14 +11,13 @@ from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from pretix.base.models import CachedFile, Event, cachedfile_name
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask
from pretix.base.shredder import ShredError
from pretix.celery_app import app
@app.task(base=ProfiledTask)
def export(event: str, shredders: List[str]) -> None:
event = Event.objects.get(id=event)
@app.task(base=ProfiledEventTask)
def export(event: Event, shredders: List[str]) -> None:
known_shredders = event.get_data_shredders()
with NamedTemporaryFile() as rawfile:
@@ -63,9 +62,8 @@ def export(event: str, shredders: List[str]) -> None:
return cf.pk
@app.task(base=ProfiledTask, throws=(ShredError,))
def shred(event: str, fileid: str, confirm_code: str) -> None:
event = Event.objects.get(id=event)
@app.task(base=ProfiledEventTask, throws=(ShredError,))
def shred(event: Event, fileid: str, confirm_code: str) -> None:
known_shredders = event.get_data_shredders()
try:
cf = CachedFile.objects.get(pk=fileid)

View File

@@ -14,10 +14,12 @@ import time
from django.conf import settings
from django.db import transaction
from django_scopes import scope, scopes_disabled
from pretix.base.metrics import (
pretix_task_duration_seconds, pretix_task_runs_total,
)
from pretix.base.models import Event
from pretix.celery_app import app
@@ -61,6 +63,35 @@ class ProfiledTask(app.Task):
return super().on_success(retval, task_id, args, kwargs)
class EventTask(app.Task):
def __call__(self, *args, **kwargs):
if 'event_id' in kwargs:
event_id = kwargs.get('event_id')
with scopes_disabled():
event = Event.objects.select_related('organizer').get(pk=event_id)
del kwargs['event_id']
kwargs['event'] = event
elif 'event' in kwargs:
event_id = kwargs.get('event')
with scopes_disabled():
event = Event.objects.select_related('organizer').get(pk=event_id)
kwargs['event'] = event
else:
args = list(args)
event_id = args[0]
with scopes_disabled():
event = Event.objects.select_related('organizer').get(pk=event_id)
args[0] = event
with scope(organizer=event.organizer):
ret = super().__call__(*args, **kwargs)
return ret
class ProfiledEventTask(ProfiledTask, EventTask):
pass
class TransactionAwareTask(ProfiledTask):
"""
Task class which is aware of django db transactions and only executes tasks

View File

@@ -4,13 +4,14 @@ import os
from django.core.files.base import ContentFile
from django.utils.timezone import now
from django.utils.translation import ugettext as _
from django_scopes import scopes_disabled
from pretix.base.i18n import language
from pretix.base.models import (
CachedCombinedTicket, CachedTicket, Event, InvoiceAddress, Order,
OrderPosition,
)
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import EventTask, ProfiledTask
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.base.signals import allow_ticket_download, register_ticket_outputs
from pretix.celery_app import app
@@ -57,10 +58,11 @@ def generate_order(order: int, provider: str):
@app.task(base=ProfiledTask)
def generate(model: str, pk: int, provider: str):
if model == 'order':
return generate_order(pk, provider)
elif model == 'orderposition':
return generate_orderposition(pk, provider)
with scopes_disabled():
if model == 'order':
return generate_order(pk, provider)
elif model == 'orderposition':
return generate_orderposition(pk, provider)
class DummyRollbackException(Exception):
@@ -165,9 +167,8 @@ def get_tickets_for_order(order, base_position=None):
return tickets
@app.task(base=ProfiledTask)
def invalidate_cache(event: int, item: int=None, provider: str=None, order: int=None, **kwargs):
event = Event.objects.get(id=event)
@app.task(base=EventTask)
def invalidate_cache(event: Event, item: int=None, provider: str=None, order: int=None, **kwargs):
qs = CachedTicket.objects.filter(order_position__order__event=event)
qsc = CachedCombinedTicket.objects.filter(order__event=event)

View File

@@ -6,6 +6,7 @@ import requests
from django.dispatch import receiver
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
from pretix import __version__
@@ -29,6 +30,7 @@ def run_update_check(sender, **kwargs):
@app.task
@scopes_disabled()
def update_check():
gs = GlobalSettingsObject()

View File

@@ -1,17 +1,17 @@
import sys
from django.dispatch import receiver
from django_scopes import scopes_disabled
from pretix.base.models import Event, User, WaitingListEntry
from pretix.base.models.waitinglist import WaitingListException
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import EventTask
from pretix.base.signals import periodic_task
from pretix.celery_app import app
@app.task(base=ProfiledTask)
def assign_automatically(event_id: int, user_id: int=None, subevent_id: int=None):
event = Event.objects.get(id=event_id)
@app.task(base=EventTask)
def assign_automatically(event: Event, user_id: int=None, subevent_id: int=None):
if user_id:
user = User.objects.get(id=user_id)
else:
@@ -69,6 +69,7 @@ def assign_automatically(event_id: int, user_id: int=None, subevent_id: int=None
@receiver(signal=periodic_task)
@scopes_disabled()
def process_waitinglist(sender, **kwargs):
qs = Event.objects.filter(
live=True

View File

@@ -3,6 +3,7 @@ import hmac
from django.conf import settings
from django.http import HttpResponse
from django_scopes import scopes_disabled
from .. import metrics
@@ -15,6 +16,7 @@ def unauthed_response():
return response
@scopes_disabled()
def serve_metrics(request):
if not settings.METRICS_ENABLED:
return unauthed_response()

View File

@@ -5,6 +5,7 @@ from django.conf import settings
from django.db.models import Q
from django.urls import Resolver404, get_script_prefix, resolve
from django.utils.translation import get_language
from django_scopes import scope
from pretix.base.models.auth import StaffSession
from pretix.base.settings import GlobalSettingsObject
@@ -53,10 +54,11 @@ def contextprocessor(request):
ctx['has_domain'] = request.event.organizer.domains.exists()
if not request.event.testmode:
complain_testmode_orders = request.event.cache.get('complain_testmode_orders')
if complain_testmode_orders is None:
complain_testmode_orders = request.event.orders.filter(testmode=True).exists()
request.event.cache.set('complain_testmode_orders', complain_testmode_orders, 30)
with scope(organizer=request.organizer):
complain_testmode_orders = request.event.cache.get('complain_testmode_orders')
if complain_testmode_orders is None:
complain_testmode_orders = request.event.orders.filter(testmode=True).exists()
request.event.cache.set('complain_testmode_orders', complain_testmode_orders, 30)
ctx['complain_testmode_orders'] = complain_testmode_orders
else:
ctx['complain_testmode_orders'] = False

View File

@@ -1,6 +1,9 @@
from django import forms
from django.urls import reverse
from django.utils.translation import pgettext_lazy
from django_scopes.forms import (
SafeModelChoiceField, SafeModelMultipleChoiceField,
)
from pretix.base.models.checkin import CheckinList
from pretix.control.forms.widgets import Select2
@@ -44,3 +47,7 @@ class CheckinListForm(forms.ModelForm):
'data-inverse-dependency': '<[name$=all_products]'
}),
}
field_classes = {
'limit_products': SafeModelMultipleChoiceField,
'subevent': SafeModelChoiceField,
}

View File

@@ -6,6 +6,9 @@ from django.urls import reverse
from django.utils.translation import (
pgettext_lazy, ugettext as __, ugettext_lazy as _,
)
from django_scopes.forms import (
SafeModelChoiceField, SafeModelMultipleChoiceField,
)
from i18nfield.forms import I18nFormField, I18nTextarea
from pretix.base.channels import get_all_sales_channels
@@ -94,6 +97,10 @@ class QuestionForm(I18nModelForm):
),
'dependency_value': forms.Select,
}
field_classes = {
'items': SafeModelMultipleChoiceField,
'dependency_question': SafeModelChoiceField,
}
class QuestionOptionForm(I18nModelForm):
@@ -159,6 +166,9 @@ class QuotaForm(I18nModelForm):
'size',
'subevent'
]
field_classes = {
'subevent': SafeModelChoiceField,
}
def save(self, *args, **kwargs):
creating = not self.instance.pk

View File

@@ -192,7 +192,7 @@ class OrderPositionAddForm(forms.Form):
label=_('Product')
)
addon_to = forms.ModelChoiceField(
OrderPosition.objects.none(),
OrderPosition.all.none(),
required=False,
label=_('Add-on to'),
)

View File

@@ -6,6 +6,7 @@ from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.utils.safestring import mark_safe
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_scopes.forms import SafeModelMultipleChoiceField
from i18nfield.forms import I18nFormField, I18nTextarea
from pretix.api.models import WebHook
@@ -149,6 +150,9 @@ class TeamForm(forms.ModelForm):
'data-inverse-dependency': '#id_all_events'
}),
}
field_classes = {
'limit_events': SafeModelMultipleChoiceField
}
def clean(self):
data = super().clean()
@@ -177,6 +181,9 @@ class DeviceForm(forms.ModelForm):
'data-inverse-dependency': '#id_all_events'
}),
}
field_classes = {
'limit_events': SafeModelMultipleChoiceField
}
class OrganizerSettingsForm(SettingsForm):
@@ -307,3 +314,6 @@ class WebHookForm(forms.ModelForm):
'data-inverse-dependency': '#id_all_events'
}),
}
field_classes = {
'limit_events': SafeModelMultipleChoiceField
}

View File

@@ -3,6 +3,7 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.models.functions import Lower
from django.urls import reverse
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from django_scopes.forms import SafeModelChoiceField
from pretix.base.forms import I18nModelForm
from pretix.base.models import Item, Voucher
@@ -35,6 +36,7 @@ class VoucherForm(I18nModelForm):
]
field_classes = {
'valid_until': SplitDateTimeField,
'subevent': SafeModelChoiceField,
}
widgets = {
'valid_until': SplitDateTimePickerWidget(),
@@ -199,6 +201,7 @@ class VoucherBulkForm(VoucherForm):
]
field_classes = {
'valid_until': SplitDateTimeField,
'subevent': SafeModelChoiceField,
}
widgets = {
'valid_until': SplitDateTimePickerWidget(),

View File

@@ -4,10 +4,11 @@ from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME, logout
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect, resolve_url
from django.template.response import TemplateResponse
from django.urls import get_script_prefix, resolve, reverse
from django.utils.deprecation import MiddlewareMixin
from django.utils.encoding import force_str
from django.utils.translation import ugettext as _
from django_scopes import scope
from hijack.templatetags.hijack_tags import is_hijacked
from pretix.base.models import Event, Organizer
@@ -17,7 +18,7 @@ from pretix.helpers.security import (
)
class PermissionMiddleware(MiddlewareMixin):
class PermissionMiddleware:
"""
This middleware enforces all requests to the control app to require login.
Additionally, it enforces all requests to "control:event." URLs
@@ -34,6 +35,10 @@ class PermissionMiddleware(MiddlewareMixin):
"user.settings.notifications.off",
)
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def _login_redirect(self, request):
# Taken from django/contrib/auth/decorators.py
path = request.build_absolute_uri()
@@ -52,19 +57,19 @@ class PermissionMiddleware(MiddlewareMixin):
return redirect_to_login(
path, resolved_login_url, REDIRECT_FIELD_NAME)
def process_request(self, request):
def __call__(self, request):
url = resolve(request.path_info)
url_name = url.url_name
if not request.path.startswith(get_script_prefix() + 'control'):
# This middleware should only touch the /control subpath
return
return self.get_response(request)
if hasattr(request, 'organizer'):
# If the user is on a organizer's subdomain, he should be redirected to pretix
return redirect(urljoin(settings.SITE_URL, request.get_full_path()))
if url_name in self.EXCEPTIONS:
return
return self.get_response(request)
if not request.user.is_authenticated:
return self._login_redirect(request)
@@ -79,10 +84,11 @@ class PermissionMiddleware(MiddlewareMixin):
return redirect(reverse('control:user.reauth') + '?next=' + quote(request.get_full_path()))
if 'event' in url.kwargs and 'organizer' in url.kwargs:
request.event = Event.objects.filter(
slug=url.kwargs['event'],
organizer__slug=url.kwargs['organizer'],
).select_related('organizer').first()
with scope(organizer=None):
request.event = Event.objects.filter(
slug=url.kwargs['event'],
organizer__slug=url.kwargs['organizer'],
).select_related('organizer').first()
if not request.event or not request.user.has_event_permission(request.event.organizer, request.event,
request=request):
raise Http404(_("The selected event was not found or you "
@@ -104,6 +110,12 @@ class PermissionMiddleware(MiddlewareMixin):
else:
request.orgapermset = request.user.get_organizer_permission_set(request.organizer)
with scope(organizer=getattr(request, 'organizer', None)):
r = self.get_response(request)
if isinstance(r, TemplateResponse):
r = r.render()
return r
class AuditLogMiddleware:

View File

@@ -7,6 +7,7 @@ from pretix.base.models import (
CachedFile, Event, OrderPosition, cachedfile_name,
)
from pretix.base.services.orders import OrderError
from pretix.base.services.tasks import EventTask
from pretix.celery_app import app
from .exporters import render_pdf
@@ -14,8 +15,8 @@ from .exporters import render_pdf
logger = logging.getLogger(__name__)
@app.task(throws=(OrderError,))
def badges_create_pdf(fileid: int, event: int, positions: List[int]) -> int:
@app.task(base=EventTask, throws=(OrderError,))
def badges_create_pdf(event: int, fileid: int, positions: List[int]) -> int:
file = CachedFile.objects.get(id=fileid)
event = Event.objects.get(id=event)

View File

@@ -223,7 +223,7 @@ class OrderPrintDo(EventPermissionRequiredMixin, AsyncAction, View):
else:
positions = [p.pk for p in order.positions.all()]
return self.do(
str(cf.id),
self.request.event.pk,
str(cf.id),
positions,
)

View File

@@ -9,6 +9,7 @@ from django.db import transaction
from django.db.models import Q
from django.utils.formats import date_format
from django.utils.translation import ugettext, ugettext_noop
from django_scopes import scope, scopes_disabled
from pretix.base.i18n import language
from pretix.base.models import (
@@ -194,51 +195,53 @@ def _get_unknown_transactions(job: BankImportJob, data: list, event: Event=None,
@app.task(base=TransactionAwareTask, bind=True, max_retries=5, default_retry_delay=1)
def process_banktransfers(self, job: int, data: list) -> None:
with language("en"): # We'll translate error messages at display time
job = BankImportJob.objects.get(pk=job)
job.state = BankImportJob.STATE_RUNNING
job.save()
prefixes = []
with scopes_disabled():
job = BankImportJob.objects.get(pk=job)
with scope(organizer=job.organizer or job.event.organizer):
job.state = BankImportJob.STATE_RUNNING
job.save()
prefixes = []
try:
# Delete left-over transactions from a failed run before so they can reimported
BankTransaction.objects.filter(state=BankTransaction.STATE_UNCHECKED, **job.owner_kwargs).delete()
transactions = _get_unknown_transactions(job, data, **job.owner_kwargs)
code_len = settings.ENTROPY['order_code']
if job.event:
pattern = re.compile(job.event.slug.upper() + r"[ \-_]*([A-Z0-9]{%s})" % code_len)
else:
if not prefixes:
prefixes = [e.slug.upper().replace(".", r"\.").replace("-", r"[\- ]*")
for e in job.organizer.events.all()]
pattern = re.compile("(%s)[ \\-_]*([A-Z0-9]{%s})" % ("|".join(prefixes), code_len))
for trans in transactions:
match = pattern.search(trans.reference.replace(" ", "").replace("\n", "").upper())
if match:
if job.event:
code = match.group(1)
_handle_transaction(trans, code, event=job.event)
else:
slug = match.group(1)
code = match.group(2)
_handle_transaction(trans, code, organizer=job.organizer, slug=slug)
else:
trans.state = BankTransaction.STATE_NOMATCH
trans.save()
except LockTimeoutException:
try:
self.retry()
except MaxRetriesExceededError:
logger.exception('Maximum number of retries exceeded for task.')
# Delete left-over transactions from a failed run before so they can reimported
BankTransaction.objects.filter(state=BankTransaction.STATE_UNCHECKED, **job.owner_kwargs).delete()
transactions = _get_unknown_transactions(job, data, **job.owner_kwargs)
code_len = settings.ENTROPY['order_code']
if job.event:
pattern = re.compile(job.event.slug.upper() + r"[ \-_]*([A-Z0-9]{%s})" % code_len)
else:
if not prefixes:
prefixes = [e.slug.upper().replace(".", r"\.").replace("-", r"[\- ]*")
for e in job.organizer.events.all()]
pattern = re.compile("(%s)[ \\-_]*([A-Z0-9]{%s})" % ("|".join(prefixes), code_len))
for trans in transactions:
match = pattern.search(trans.reference.replace(" ", "").replace("\n", "").upper())
if match:
if job.event:
code = match.group(1)
_handle_transaction(trans, code, event=job.event)
else:
slug = match.group(1)
code = match.group(2)
_handle_transaction(trans, code, organizer=job.organizer, slug=slug)
else:
trans.state = BankTransaction.STATE_NOMATCH
trans.save()
except LockTimeoutException:
try:
self.retry()
except MaxRetriesExceededError:
logger.exception('Maximum number of retries exceeded for task.')
job.state = BankImportJob.STATE_ERROR
job.save()
except Exception as e:
job.state = BankImportJob.STATE_ERROR
job.save()
except Exception as e:
job.state = BankImportJob.STATE_ERROR
job.save()
raise e
else:
job.state = BankImportJob.STATE_COMPLETED
job.save()
raise e
else:
job.state = BankImportJob.STATE_COMPLETED
job.save()

View File

@@ -13,6 +13,7 @@ from django.utils.translation import ugettext_lazy as _
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django_scopes import scopes_disabled
from paypalrestsdk.openid_connect import Tokeninfo
from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
@@ -133,6 +134,7 @@ def abort(request, *args, **kwargs):
@csrf_exempt
@require_POST
@scopes_disabled()
def webhook(request, *args, **kwargs):
event_body = request.body.decode('utf-8').strip()
event_json = json.loads(event_body)

View File

@@ -1,6 +1,9 @@
from django import forms
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django_scopes.forms import (
SafeModelChoiceField, SafeModelMultipleChoiceField,
)
from pretix.control.forms.widgets import Select2
from pretix.plugins.pretixdroid.models import AppConfiguration
@@ -16,6 +19,10 @@ class AppConfigurationForm(forms.ModelForm):
}),
'app': forms.RadioSelect
}
field_classes = {
'items': SafeModelMultipleChoiceField,
'list': SafeModelChoiceField,
}
def __init__(self, **kwargs):
self.event = kwargs.pop('event')

View File

@@ -17,6 +17,7 @@ from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView, View
from django_scopes import scope, scopes_disabled
from pretix.base.models import Checkin, Event, Order, OrderPosition
from pretix.base.models.event import SubEvent
@@ -124,34 +125,35 @@ class ConfigView(EventPermissionRequiredMixin, TemplateView):
class ApiView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, **kwargs):
try:
self.event = Event.objects.get(
slug=self.kwargs['event'],
organizer__slug=self.kwargs['organizer']
)
except Event.DoesNotExist:
return HttpResponseNotFound('Unknown event')
with scopes_disabled():
try:
self.event = Event.objects.get(
slug=self.kwargs['event'],
organizer__slug=self.kwargs['organizer']
)
except Event.DoesNotExist:
return HttpResponseNotFound('Unknown event')
with scope(organizer=self.event.organizer):
try:
self.config = self.event.appconfiguration_set.get(key=request.GET.get("key", "-unset-"))
except AppConfiguration.DoesNotExist:
return HttpResponseForbidden('Invalid key')
try:
self.config = self.event.appconfiguration_set.get(key=request.GET.get("key", "-unset-"))
except AppConfiguration.DoesNotExist:
return HttpResponseForbidden('Invalid key')
self.subevent = None
if self.event.has_subevents:
if self.config.list.subevent:
self.subevent = self.config.list.subevent
if 'subevent' in kwargs and kwargs['subevent'] != str(self.subevent.pk):
return HttpResponseForbidden('Invalid subevent selected.')
elif 'subevent' in kwargs:
self.subevent = get_object_or_404(SubEvent, event=self.event, pk=kwargs['subevent'])
self.subevent = None
if self.event.has_subevents:
if self.config.list.subevent:
self.subevent = self.config.list.subevent
if 'subevent' in kwargs and kwargs['subevent'] != str(self.subevent.pk):
return HttpResponseForbidden('Invalid subevent selected.')
elif 'subevent' in kwargs:
self.subevent = get_object_or_404(SubEvent, event=self.event, pk=kwargs['subevent'])
else:
return HttpResponseForbidden('No subevent selected.')
else:
return HttpResponseForbidden('No subevent selected.')
else:
if 'subevent' in kwargs:
return HttpResponseForbidden('Subevents not enabled.')
if 'subevent' in kwargs:
return HttpResponseForbidden('Subevents not enabled.')
return super().dispatch(request, **kwargs)
return super().dispatch(request, **kwargs)
class ApiRedeemView(ApiView):

View File

@@ -5,15 +5,14 @@ from i18nfield.strings import LazyI18nString
from pretix.base.i18n import language
from pretix.base.models import Event, InvoiceAddress, Order, User
from pretix.base.services.mail import SendMailException, mail
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask
from pretix.celery_app import app
from pretix.multidomain.urlreverse import build_absolute_uri
@app.task(base=ProfiledTask)
def send_mails(event: int, user: int, subject: dict, message: dict, orders: list, items: list, recipients: str) -> None:
@app.task(base=ProfiledEventTask)
def send_mails(event: Event, user: int, subject: dict, message: dict, orders: list, items: list, recipients: str) -> None:
failures = []
event = Event.objects.get(pk=event)
user = User.objects.get(pk=user) if user else None
orders = Order.objects.filter(pk__in=orders, event=event)
subject = LazyI18nString(subject)

View File

@@ -1,5 +1,6 @@
import stripe
from django.core.management.base import BaseCommand
from django_scopes import scopes_disabled
from pretix.base.models import Event
from pretix.base.settings import GlobalSettingsObject
@@ -8,6 +9,7 @@ from pretix.base.settings import GlobalSettingsObject
class Command(BaseCommand):
help = "Detect country for Stripe Connect accounts connected with pretix 2.0 (required for payment request buttons)"
@scopes_disabled()
def handle(self, *args, **options):
cache = {}
gs = GlobalSettingsObject()

View File

@@ -5,6 +5,7 @@ import stripe
from django.conf import settings
from pretix.base.models import Event
from pretix.base.services.tasks import EventTask
from pretix.celery_app import app
from pretix.multidomain.urlreverse import get_domain
from pretix.plugins.stripe.models import RegisteredApplePayDomain
@@ -27,7 +28,7 @@ def get_stripe_account_key(prov):
return prov.settings.publishable_key
@app.task(max_retries=5, default_retry_delay=1)
@app.task(base=EventTask, max_retries=5, default_retry_delay=1)
def stripe_verify_domain(event_id, domain):
from pretix.plugins.stripe.payment import StripeCC
event = Event.objects.get(pk=event_id)

View File

@@ -17,6 +17,7 @@ from django.views import View
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django_scopes import scopes_disabled
from pretix.base.models import Event, Order, OrderPayment, Quota
from pretix.base.payment import PaymentException
@@ -140,6 +141,7 @@ def oauth_return(request, *args, **kwargs):
@csrf_exempt
@require_POST
@scopes_disabled()
def webhook(request, *args, **kwargs):
event_json = json.loads(request.body.decode('utf-8'))

View File

@@ -12,6 +12,7 @@ from django.utils.translation import (
get_language, pgettext_lazy, ugettext_lazy as _,
)
from django.views.generic.base import TemplateResponseMixin
from django_scopes import scopes_disabled
from pretix.base.models import Order
from pretix.base.models.orders import InvoiceAddress, OrderPayment
@@ -114,7 +115,10 @@ class BaseCheckoutFlowStep:
self.request._checkout_flow_invoice_address = InvoiceAddress()
else:
try:
self.request._checkout_flow_invoice_address = InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
with scopes_disabled():
self.request._checkout_flow_invoice_address = InvoiceAddress.objects.get(
pk=iapk, order__isnull=True
)
except InvoiceAddress.DoesNotExist:
self.request._checkout_flow_invoice_address = InvoiceAddress()
return self.request._checkout_flow_invoice_address

View File

@@ -4,6 +4,7 @@ from django.conf import settings
from django.core.files.base import ContentFile, File
from django.core.files.storage import default_storage
from django.core.management.base import BaseCommand
from django_scopes import scopes_disabled
from pretix.base.models import Event_SettingsStore, Organizer_SettingsStore
from pretix.base.settings import GlobalSettingsObject
@@ -15,6 +16,7 @@ from ...style import regenerate_css, regenerate_organizer_css
class Command(BaseCommand):
help = "Re-generate all custom stylesheets and scripts"
@scopes_disabled()
def handle(self, *args, **options):
for es in Organizer_SettingsStore.objects.filter(key="presale_css_file"):
regenerate_organizer_css.apply_async(args=(es.object_id,))

View File

@@ -1,25 +1,32 @@
from django.urls import resolve
from django.utils.deprecation import MiddlewareMixin
from django_scopes import scope
from pretix.presale.signals import process_response
from .utils import _detect_event
class EventMiddleware(MiddlewareMixin):
def process_request(self, request):
class EventMiddleware:
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def __call__(self, request):
url = resolve(request.path_info)
request._namespace = url.namespace
if url.namespace != 'presale':
return
return self.get_response(request)
if 'organizer' in url.kwargs or 'event' in url.kwargs:
redirect = _detect_event(request, require_live=url.url_name != 'event.widget.productlist')
if redirect:
return redirect
def process_response(self, request, response):
if hasattr(request, '_namespace') and request._namespace == 'presale' and hasattr(request, 'event'):
for receiver, r in process_response.send(request.event, request=request, response=response):
response = r
with scope(organizer=getattr(request, 'organizer', None)):
response = self.get_response(request)
if hasattr(request, '_namespace') and request._namespace == 'presale' and hasattr(request, 'event'):
for receiver, r in process_response.send(request.event, request=request, response=response):
response = r
return response

View File

@@ -11,9 +11,10 @@ from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.dispatch import Signal
from django.templatetags.static import static as _static
from django_scopes import scope
from pretix.base.models import Event, Event_SettingsStore, Organizer
from pretix.base.services.tasks import ProfiledTask
from pretix.base.services.tasks import ProfiledEventTask, ProfiledTask
from pretix.celery_app import app
from pretix.multidomain.urlreverse import get_domain
from pretix.presale.signals import sass_postamble, sass_preamble
@@ -78,10 +79,8 @@ def compile_scss(object, file="main.scss", fonts=True):
return css, checksum
@app.task(base=ProfiledTask)
def regenerate_css(event_id: int):
event = Event.objects.select_related('organizer').get(pk=event_id)
@app.task(base=ProfiledEventTask)
def regenerate_css(event):
# main.scss
css, checksum = compile_scss(event)
fname = 'pub/{}/{}/presale.{}.css'.format(event.organizer.slug, event.slug, checksum[:16])
@@ -105,28 +104,29 @@ def regenerate_css(event_id: int):
def regenerate_organizer_css(organizer_id: int):
organizer = Organizer.objects.get(pk=organizer_id)
# main.scss
css, checksum = compile_scss(organizer)
fname = 'pub/{}/presale.{}.css'.format(organizer.slug, checksum[:16])
if organizer.settings.get('presale_css_checksum', '') != checksum:
newname = default_storage.save(fname, ContentFile(css.encode('utf-8')))
organizer.settings.set('presale_css_file', newname)
organizer.settings.set('presale_css_checksum', checksum)
with scope(organizer=organizer):
# main.scss
css, checksum = compile_scss(organizer)
fname = 'pub/{}/presale.{}.css'.format(organizer.slug, checksum[:16])
if organizer.settings.get('presale_css_checksum', '') != checksum:
newname = default_storage.save(fname, ContentFile(css.encode('utf-8')))
organizer.settings.set('presale_css_file', newname)
organizer.settings.set('presale_css_checksum', checksum)
# widget.scss
css, checksum = compile_scss(organizer, file='widget.scss', fonts=False)
fname = 'pub/{}/widget.{}.css'.format(organizer.slug, checksum[:16])
if organizer.settings.get('presale_widget_css_checksum', '') != checksum:
newname = default_storage.save(fname, ContentFile(css.encode('utf-8')))
organizer.settings.set('presale_widget_css_file', newname)
organizer.settings.set('presale_widget_css_checksum', checksum)
# widget.scss
css, checksum = compile_scss(organizer, file='widget.scss', fonts=False)
fname = 'pub/{}/widget.{}.css'.format(organizer.slug, checksum[:16])
if organizer.settings.get('presale_widget_css_checksum', '') != checksum:
newname = default_storage.save(fname, ContentFile(css.encode('utf-8')))
organizer.settings.set('presale_widget_css_file', newname)
organizer.settings.set('presale_widget_css_checksum', checksum)
non_inherited_events = set(Event_SettingsStore.objects.filter(
object__organizer=organizer, key__in=affected_keys
).values_list('object_id', flat=True))
for event in organizer.events.all():
if event.pk not in non_inherited_events:
regenerate_css.apply_async(args=(event.pk,))
non_inherited_events = set(Event_SettingsStore.objects.filter(
object__organizer=organizer, key__in=affected_keys
).values_list('object_id', flat=True))
for event in organizer.events.all():
if event.pk not in non_inherited_events:
regenerate_css.apply_async(args=(event.pk,))
register_fonts = Signal()

View File

@@ -8,6 +8,7 @@ from django.http import Http404
from django.shortcuts import redirect
from django.urls import resolve
from django.utils.translation import ugettext_lazy as _
from django_scopes import scope
from pretix.base.middleware import LocaleMiddleware
from pretix.base.models import Event, Organizer
@@ -17,6 +18,7 @@ from pretix.presale.signals import process_request, process_response
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
@scope(organizer=None)
def _detect_event(request, require_live=True, require_plugin=None):
if hasattr(request, '_event_detected'):
return
@@ -151,10 +153,11 @@ def _event_view(function=None, require_live=True, require_plugin=None):
if ret:
return ret
else:
response = func(request=request, *args, **kwargs)
for receiver, r in process_response.send(request.event, request=request, response=response):
response = r
return response
with scope(organizer=getattr(request, 'organizer', None)):
response = func(request=request, *args, **kwargs)
for receiver, r in process_response.send(request.event, request=request, response=response):
response = r
return response
for attrname in dir(func):
# Preserve flags like csrf_exempt

View File

@@ -9,6 +9,7 @@ from django.db.models import Prefetch, Sum
from django.utils.decorators import available_attrs
from django.utils.functional import cached_property
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.i18n import language
from pretix.base.models import (
@@ -40,7 +41,10 @@ class CartMixin:
self.request._checkout_flow_invoice_address = InvoiceAddress()
else:
try:
self.request._checkout_flow_invoice_address = InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
with scopes_disabled():
self.request._checkout_flow_invoice_address = InvoiceAddress.objects.get(
pk=iapk, order__isnull=True
)
except InvoiceAddress.DoesNotExist:
self.request._checkout_flow_invoice_address = InvoiceAddress()
return self.request._checkout_flow_invoice_address
@@ -215,7 +219,8 @@ def get_cart_invoice_address(request):
request._checkout_flow_invoice_address = InvoiceAddress()
else:
try:
request._checkout_flow_invoice_address = InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
with scopes_disabled():
request._checkout_flow_invoice_address = InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
except InvoiceAddress.DoesNotExist:
request._checkout_flow_invoice_address = InvoiceAddress()
return request._checkout_flow_invoice_address

View File

@@ -17,6 +17,7 @@ from django.utils.timezone import now
from django.utils.translation import ugettext as _
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import TemplateView, View
from django_scopes import scopes_disabled
from pretix.base.models import (
CartPosition, InvoiceAddress, QuestionAnswer, SubEvent, Voucher,
@@ -80,7 +81,8 @@ class CartActionMixin:
return InvoiceAddress()
try:
return InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
with scopes_disabled():
return InvoiceAddress.objects.get(pk=iapk, order__isnull=True)
except InvoiceAddress.DoesNotExist:
return InvoiceAddress()

View File

@@ -343,6 +343,7 @@ MIDDLEWARE = [
'pretix.base.middleware.LocaleMiddleware',
'pretix.base.middleware.SecurityMiddleware',
'pretix.presale.middleware.EventMiddleware',
'pretix.api.middleware.ApiScopeMiddleware',
]
try:

View File

@@ -0,0 +1,10 @@
from django_scopes import scope
def classscope(attr='o'):
def wrap(fn):
def wrapped(self, *args, **kwargs):
with scope(organizer=getattr(self, attr)):
return fn(self, *args, **kwargs)
return wrapped
return wrap

View File

@@ -12,6 +12,7 @@ from pretix.settings import * # NOQA
DATA_DIR = tmpdir.name
LOG_DIR = os.path.join(DATA_DIR, 'logs')
MEDIA_ROOT = os.path.join(DATA_DIR, 'media')
SITE_URL = "http://example.com"
atexit.register(tmpdir.cleanup)

View File

@@ -9,6 +9,7 @@ django-formset-js-improved==0.5.0.2
django-compressor==2.2.*
django-hierarkey==1.0.*,>=1.0.3
django-filter==2.1.*
django-scopes==1.1.*
reportlab==3.5.*
PyPDF2==1.26.*
Pillow==5.*

View File

@@ -97,6 +97,7 @@ setup(
'django-compressor==2.2.*',
'django-hierarkey==1.0.*,>=1.0.2',
'django-filter==2.1.*',
'django-scopes==1.1.*',
'reportlab==3.5.*',
'Pillow==5.*',
'PyPDF2==1.26.*',

View File

@@ -1,7 +1,9 @@
from datetime import datetime
import pytest
from django.test import utils
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pytz import UTC
from rest_framework.test import APIClient
@@ -15,16 +17,19 @@ def client():
@pytest.fixture
@scopes_disabled()
def organizer():
return Organizer.objects.create(name='Dummy', slug='dummy')
@pytest.fixture
@scopes_disabled()
def meta_prop(organizer):
return organizer.meta_properties.create(name="type", default="Concert")
@pytest.fixture
@scopes_disabled()
def event(organizer, meta_prop):
e = Event.objects.create(
organizer=organizer, name='Dummy', slug='dummy',
@@ -37,6 +42,7 @@ def event(organizer, meta_prop):
@pytest.fixture
@scopes_disabled()
def event2(organizer, meta_prop):
e = Event.objects.create(
organizer=organizer, name='Dummy2', slug='dummy2',
@@ -48,6 +54,7 @@ def event2(organizer, meta_prop):
@pytest.fixture
@scopes_disabled()
def event3(organizer, meta_prop):
e = Event.objects.create(
organizer=organizer, name='Dummy3', slug='dummy3',
@@ -59,6 +66,7 @@ def event3(organizer, meta_prop):
@pytest.fixture
@scopes_disabled()
def team(organizer):
return Team.objects.create(
organizer=organizer,
@@ -73,6 +81,7 @@ def team(organizer):
@pytest.fixture
@scopes_disabled()
def device(organizer):
return Device.objects.create(
organizer=organizer,
@@ -89,6 +98,7 @@ def user():
@pytest.fixture
@scopes_disabled()
def user_client(client, team, user):
team.can_view_orders = True
team.can_view_vouchers = True
@@ -100,6 +110,7 @@ def user_client(client, team, user):
@pytest.fixture
@scopes_disabled()
def token_client(client, team):
team.can_view_orders = True
team.can_view_vouchers = True
@@ -117,6 +128,7 @@ def device_client(client, device):
@pytest.fixture
@scopes_disabled()
def subevent(event, meta_prop):
event.has_subevents = True
event.save()
@@ -127,6 +139,7 @@ def subevent(event, meta_prop):
@pytest.fixture
@scopes_disabled()
def subevent2(event2, meta_prop):
event2.has_subevents = True
event2.save()
@@ -137,10 +150,15 @@ def subevent2(event2, meta_prop):
@pytest.fixture
@scopes_disabled()
def taxrule(event):
return event.tax_rules.create(name="VAT", rate=19)
@pytest.fixture
@scopes_disabled()
def taxrule2(event2):
return event2.tax_rules.create(name="VAT", rate=25)
utils.setup_databases = scopes_disabled()(utils.setup_databases)

View File

@@ -13,7 +13,6 @@ def test_no_auth(client):
def test_session_auth_no_teams(client, user):
client.login(email=user.email, password='dummy')
resp = client.get('/api/v1/organizers/')
print(resp.data)
assert resp.status_code == 200
assert len(resp.data['results']) == 0

View File

@@ -5,6 +5,7 @@ from unittest import mock
import pytest
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import Question
@@ -175,7 +176,8 @@ def test_cartpos_create(token_client, organizer, event, item, quota, question):
), format='json', data=res
)
assert resp.status_code == 201
cp = CartPosition.objects.get(pk=resp.data['id'])
with scopes_disabled():
cp = CartPosition.objects.get(pk=resp.data['id'])
assert cp.price == Decimal('23.00')
assert cp.item == item
assert cp.attendee_name_parts == {'full_name': 'Peter'}
@@ -193,7 +195,8 @@ def test_cartpos_create_name_optional(token_client, organizer, event, item, quot
), format='json', data=res
)
assert resp.status_code == 201
cp = CartPosition.objects.get(pk=resp.data['id'])
with scopes_disabled():
cp = CartPosition.objects.get(pk=resp.data['id'])
assert cp.price == Decimal('23.00')
assert cp.item == item
assert cp.attendee_name_parts == {}
@@ -217,7 +220,8 @@ def test_cartpos_create_legacy_name(token_client, organizer, event, item, quota,
), format='json', data=res
)
assert resp.status_code == 201
cp = CartPosition.objects.get(pk=resp.data['id'])
with scopes_disabled():
cp = CartPosition.objects.get(pk=resp.data['id'])
assert cp.price == Decimal('23.00')
assert cp.item == item
assert cp.attendee_name_parts == {'_legacy': 'Peter'}
@@ -247,7 +251,8 @@ def test_cartpos_cart_id_optional(token_client, organizer, event, item, quota, q
), format='json', data=res
)
assert resp.status_code == 201
cp = CartPosition.objects.get(pk=resp.data['id'])
with scopes_disabled():
cp = CartPosition.objects.get(pk=resp.data['id'])
assert cp.price == Decimal('23.00')
assert cp.item == item
assert len(cp.cart_id) > 48
@@ -300,7 +305,8 @@ def test_cartpos_create_item_validation(token_client, organizer, event, item, it
assert resp.status_code == 400
assert resp.data == {'item': ['The specified item does not belong to this event.']}
var2 = item2.variations.create(value="A")
with scopes_disabled():
var2 = item2.variations.create(value="A")
res['item'] = item.pk
res['variation'] = var2.pk
@@ -312,7 +318,8 @@ def test_cartpos_create_item_validation(token_client, organizer, event, item, it
assert resp.status_code == 400
assert resp.data == {'non_field_errors': ['You cannot specify a variation for this item.']}
var1 = item.variations.create(value="A")
with scopes_disabled():
var1 = item.variations.create(value="A")
res['item'] = item.pk
res['variation'] = var1.pk
resp = token_client.post(
@@ -361,7 +368,8 @@ def test_cartpos_expires_optional(token_client, organizer, event, item, quota, q
), format='json', data=res
)
assert resp.status_code == 201
cp = CartPosition.objects.get(pk=resp.data['id'])
with scopes_disabled():
cp = CartPosition.objects.get(pk=resp.data['id'])
assert cp.price == Decimal('23.00')
assert cp.item == item
assert cp.expires - now() > datetime.timedelta(minutes=25)
@@ -410,7 +418,8 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
assert resp.data == {
'answers': [{'non_field_errors': ['You need to specify options if the question is of a choice type.']}]}
question.options.create(answer="L")
with scopes_disabled():
question.options.create(answer="L")
res['answers'][0]['options'] = [
question.options.first().pk,
question.options.last().pk,
@@ -445,8 +454,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.question == question
assert answ.answer == "XL, L"
@@ -460,8 +470,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "3.45"
question.type = Question.TYPE_NUMBER
@@ -486,8 +497,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "True"
question.type = Question.TYPE_BOOLEAN
@@ -499,8 +511,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "False"
question.type = Question.TYPE_BOOLEAN
@@ -523,8 +536,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "2018-05-14"
question.type = Question.TYPE_DATE
@@ -548,8 +562,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "2018-05-14 13:00:00+00:00"
question.type = Question.TYPE_DATETIME
@@ -574,8 +589,9 @@ def test_cartpos_create_answer_validation(token_client, organizer, event, item,
), format='json', data=res
)
assert resp.status_code == 201
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
with scopes_disabled():
pos = CartPosition.objects.get(pk=resp.data['id'])
answ = pos.answers.first()
assert answ.answer == "13:00:00"
question.type = Question.TYPE_TIME

View File

@@ -6,6 +6,7 @@ from unittest import mock
import pytest
from django.utils.timezone import now
from django_countries.fields import Country
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
from pytz import UTC
@@ -157,7 +158,8 @@ def test_list_list(token_client, organizer, event, clist, item, subevent):
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/checkinlists/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
assert [res] == resp.data['results']
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
with scopes_disabled():
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/checkinlists/?subevent={}'.format(organizer.slug, event.slug, se2.pk))
assert [] == resp.data['results']
@@ -188,10 +190,11 @@ def test_list_create(token_client, organizer, event, item, item_on_wrong_event):
format='json'
)
assert resp.status_code == 201
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
assert cl.limit_products.count() == 1
assert not cl.all_products
with scopes_disabled():
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
assert cl.limit_products.count() == 1
assert not cl.all_products
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/checkinlists/'.format(organizer.slug, event.slug),
@@ -271,18 +274,20 @@ def test_list_update(token_client, organizer, event, clist):
format='json'
)
assert resp.status_code == 200
cl = CheckinList.objects.get(pk=resp.data['id'])
with scopes_disabled():
cl = CheckinList.objects.get(pk=resp.data['id'])
assert cl.name == "VIP"
@pytest.mark.django_db
def test_list_all_items_positions(token_client, organizer, event, clist, clist_all, item, other_item, order):
p1 = dict(TEST_ORDERPOSITION1_RES)
p1["id"] = order.positions.first().pk
p1["item"] = item.pk
p2 = dict(TEST_ORDERPOSITION2_RES)
p2["id"] = order.positions.last().pk
p2["item"] = other_item.pk
with scopes_disabled():
p1 = dict(TEST_ORDERPOSITION1_RES)
p1["id"] = order.positions.first().pk
p1["item"] = item.pk
p2 = dict(TEST_ORDERPOSITION2_RES)
p2["id"] = order.positions.last().pk
p2["item"] = other_item.pk
# All items
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/?ordering=positionid'.format(
@@ -292,7 +297,8 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
assert [p1, p2] == resp.data['results']
# Check-ins on other list ignored
order.positions.first().checkins.create(list=clist)
with scopes_disabled():
order.positions.first().checkins.create(list=clist)
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/?ordering=positionid'.format(
organizer.slug, event.slug, clist_all.pk
))
@@ -305,7 +311,8 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
assert [] == resp.data['results']
# Only checked in
c = order.positions.first().checkins.create(list=clist_all)
with scopes_disabled():
c = order.positions.first().checkins.create(list=clist_all)
p1['checkins'] = [
{
'list': clist_all.pk,
@@ -341,7 +348,8 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
# Order by checkin date
time.sleep(1)
c = order.positions.last().checkins.create(list=clist_all)
with scopes_disabled():
c = order.positions.last().checkins.create(list=clist_all)
p2['checkins'] = [
{
'list': clist_all.pk,
@@ -388,7 +396,8 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
@pytest.mark.django_db
def test_list_limited_items_positions(token_client, organizer, event, clist, item, order):
p1 = dict(TEST_ORDERPOSITION1_RES)
p1["id"] = order.positions.first().pk
with scopes_disabled():
p1["id"] = order.positions.first().pk
p1["item"] = item.pk
# All items
@@ -402,12 +411,13 @@ def test_list_limited_items_positions(token_client, organizer, event, clist, ite
@pytest.mark.django_db
def test_list_limited_items_position_detail(token_client, organizer, event, clist, item, order):
p1 = dict(TEST_ORDERPOSITION1_RES)
p1["id"] = order.positions.first().pk
with scopes_disabled():
p1["id"] = order.positions.first().pk
p1["item"] = item.pk
# All items
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p1["id"]
))
assert resp.status_code == 200
assert p1 == resp.data
@@ -415,12 +425,13 @@ def test_list_limited_items_position_detail(token_client, organizer, event, clis
@pytest.mark.django_db
def test_status(token_client, organizer, event, clist_all, item, other_item, order):
op = order.positions.first()
var1 = item.variations.create(value="XS")
var2 = item.variations.create(value="S")
op.variation = var1
op.save()
Checkin.objects.create(position=op, list=clist_all)
with scopes_disabled():
op = order.positions.first()
var1 = item.variations.create(value="XS")
var2 = item.variations.create(value="S")
op.variation = var1
op.save()
Checkin.objects.create(position=op, list=clist_all)
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/status/'.format(
organizer.slug, event.slug, clist_all.pk,
))
@@ -464,21 +475,25 @@ def test_status(token_client, organizer, event, clist_all, item, other_item, ord
def test_custom_datetime(token_client, organizer, clist, event, order):
dt = now() - datetime.timedelta(days=1)
dt = dt.replace(microsecond=0)
with scopes_disabled():
p = order.positions.first().pk
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p
), {
'datetime': dt.isoformat()
}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
assert Checkin.objects.last().datetime == dt
with scopes_disabled():
assert Checkin.objects.last().datetime == dt
@pytest.mark.django_db
def test_name_fallback(token_client, organizer, clist, event, order):
order.invoice_address.name_parts = {'_legacy': 'Paul'}
order.invoice_address.save()
op = order.positions.first()
with scopes_disabled():
op = order.positions.first()
op.attendee_name_cached = None
op.attendee_name_parts = {}
op.save()
@@ -493,8 +508,10 @@ def test_name_fallback(token_client, organizer, clist, event, order):
@pytest.mark.django_db
def test_by_secret(token_client, organizer, clist, event, order):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().secret
organizer.slug, event.slug, clist.pk, p.secret
), {}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -502,13 +519,15 @@ def test_by_secret(token_client, organizer, clist, event, order):
@pytest.mark.django_db
def test_only_once(token_client, organizer, clist, event, order):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'error'
@@ -517,13 +536,15 @@ def test_only_once(token_client, organizer, clist, event, order):
@pytest.mark.django_db
def test_reupload_same_nonce(token_client, organizer, clist, event, order):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'nonce': 'foobar'}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'nonce': 'foobar'}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -531,13 +552,15 @@ def test_reupload_same_nonce(token_client, organizer, clist, event, order):
@pytest.mark.django_db
def test_multiple_different_list(token_client, organizer, clist, clist_all, event, order):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'nonce': 'foobar'}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist_all.pk, order.positions.first().pk
organizer.slug, event.slug, clist_all.pk, p.pk
), {'nonce': 'baz'}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -545,13 +568,15 @@ def test_multiple_different_list(token_client, organizer, clist, clist_all, even
@pytest.mark.django_db
def test_forced_multiple(token_client, organizer, clist, event, order):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'force': True}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -559,17 +584,19 @@ def test_forced_multiple(token_client, organizer, clist, event, order):
@pytest.mark.django_db
def test_require_paid(token_client, organizer, clist, event, order):
with scopes_disabled():
p = order.positions.first()
order.status = Order.STATUS_PENDING
order.save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'error'
assert resp.data['reason'] == 'unpaid'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'ignore_unpaid': True}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'error'
@@ -579,14 +606,14 @@ def test_require_paid(token_client, organizer, clist, event, order):
clist.save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'error'
assert resp.data['reason'] == 'unpaid'
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'ignore_unpaid': True}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -603,88 +630,105 @@ def question(event, item):
@pytest.mark.django_db
def test_question_number(token_client, organizer, clist, event, order, question):
question[0].options.all().delete()
with scopes_disabled():
p = order.positions.first()
question[0].options.all().delete()
question[0].type = 'N'
question[0].save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: "3.24"}}, format='json')
print(resp.data)
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
assert order.positions.first().answers.get(question=question[0]).answer == '3.24'
with scopes_disabled():
assert order.positions.first().answers.get(question=question[0]).answer == '3.24'
@pytest.mark.django_db
def test_question_choice(token_client, organizer, clist, event, order, question):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: str(question[1].pk)}}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
assert order.positions.first().answers.get(question=question[0]).answer == 'M'
assert list(order.positions.first().answers.get(question=question[0]).options.all()) == [question[1]]
with scopes_disabled():
assert order.positions.first().answers.get(question=question[0]).answer == 'M'
assert list(order.positions.first().answers.get(question=question[0]).options.all()) == [question[1]]
@pytest.mark.django_db
def test_question_invalid(token_client, organizer, clist, event, order, question):
with scopes_disabled():
p = order.positions.first()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: "A"}}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
@pytest.mark.django_db
def test_question_required(token_client, organizer, clist, event, order, question):
with scopes_disabled():
p = order.positions.first()
question[0].required = True
question[0].save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: ""}}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
@pytest.mark.django_db
def test_question_optional(token_client, organizer, clist, event, order, question):
with scopes_disabled():
p = order.positions.first()
question[0].required = False
question[0].save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: ""}}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
@@ -692,20 +736,24 @@ def test_question_optional(token_client, organizer, clist, event, order, questio
@pytest.mark.django_db
def test_question_multiple_choice(token_client, organizer, clist, event, order, question):
with scopes_disabled():
p = order.positions.first()
question[0].type = 'M'
question[0].save()
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {}, format='json')
assert resp.status_code == 400
assert resp.data['status'] == 'incomplete'
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
with scopes_disabled():
assert resp.data['questions'] == [QuestionSerializer(question[0]).data]
resp = token_client.post('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/{}/redeem/'.format(
organizer.slug, event.slug, clist.pk, order.positions.first().pk
organizer.slug, event.slug, clist.pk, p.pk
), {'answers': {question[0].pk: "{},{}".format(question[1].pk, question[2].pk)}}, format='json')
assert resp.status_code == 201
assert resp.data['status'] == 'ok'
assert order.positions.first().answers.get(question=question[0]).answer == 'M, L'
assert set(order.positions.first().answers.get(question=question[0]).options.all()) == {question[1], question[2]}
with scopes_disabled():
assert order.positions.first().answers.get(question=question[0]).answer == 'M, L'
assert set(order.positions.first().answers.get(question=question[0]).options.all()) == {question[1], question[2]}

View File

@@ -5,6 +5,7 @@ from unittest import mock
import pytest
from django.conf import settings
from django_countries.fields import Country
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import Event, InvoiceAddress, Order, OrderPosition
@@ -161,11 +162,12 @@ def test_event_create(token_client, organizer, event, meta_prop):
format='json'
)
assert resp.status_code == 201
assert not organizer.events.get(slug="2030").testmode
assert organizer.events.get(slug="2030").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
assert organizer.events.get(slug="2030").plugins == settings.PRETIX_PLUGINS_DEFAULT
with scopes_disabled():
assert not organizer.events.get(slug="2030").testmode
assert organizer.events.get(slug="2030").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
assert organizer.events.get(slug="2030").plugins == settings.PRETIX_PLUGINS_DEFAULT
resp = token_client.post(
'/api/v1/organizers/{}/events/'.format(organizer.slug),
@@ -278,13 +280,14 @@ def test_event_create_with_clone(token_client, organizer, event, meta_prop):
)
assert resp.status_code == 201
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2030')
assert cloned_event.plugins == 'pretix.plugins.ticketoutputpdf'
assert cloned_event.is_public is False
assert cloned_event.testmode
assert organizer.events.get(slug="2030").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
with scopes_disabled():
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2030')
assert cloned_event.plugins == 'pretix.plugins.ticketoutputpdf'
assert cloned_event.is_public is False
assert cloned_event.testmode
assert organizer.events.get(slug="2030").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug),
@@ -310,12 +313,13 @@ def test_event_create_with_clone(token_client, organizer, event, meta_prop):
)
assert resp.status_code == 201
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2031')
assert cloned_event.plugins == "pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf"
assert cloned_event.is_public is True
assert organizer.events.get(slug="2031").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
with scopes_disabled():
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2031')
assert cloned_event.plugins == "pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf"
assert cloned_event.is_public is True
assert organizer.events.get(slug="2031").meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/clone/'.format(organizer.slug, event.slug),
@@ -339,8 +343,9 @@ def test_event_create_with_clone(token_client, organizer, event, meta_prop):
)
assert resp.status_code == 201
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2032')
assert cloned_event.plugins == ""
with scopes_disabled():
cloned_event = Event.objects.get(organizer=organizer.pk, slug='2032')
assert cloned_event.plugins == ""
@pytest.mark.django_db
@@ -388,11 +393,12 @@ def test_event_update(token_client, organizer, event, item, meta_prop):
format='json'
)
assert resp.status_code == 200
event = Event.objects.get(organizer=organizer.pk, slug=resp.data['slug'])
assert event.currency == "DKK"
assert organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
with scopes_disabled():
event = Event.objects.get(organizer=organizer.pk, slug=resp.data['slug'])
assert event.currency == "DKK"
assert organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug),
@@ -447,9 +453,10 @@ def test_event_update(token_client, organizer, event, item, meta_prop):
format='json'
)
assert resp.status_code == 200
assert organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name, value="Workshop"
).exists()
with scopes_disabled():
assert organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name, value="Workshop"
).exists()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug),
@@ -460,9 +467,10 @@ def test_event_update(token_client, organizer, event, item, meta_prop):
format='json'
)
assert resp.status_code == 200
assert not organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name
).exists()
with scopes_disabled():
assert not organizer.events.get(slug=resp.data['slug']).meta_values.filter(
property__name=meta_prop.name
).exists()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug),
@@ -598,7 +606,8 @@ def test_event_detail(token_client, organizer, event, team):
def test_event_delete(token_client, organizer, event):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/'.format(organizer.slug, event.slug))
assert resp.status_code == 204
assert not organizer.events.filter(pk=event.id).exists()
with scopes_disabled():
assert not organizer.events.filter(pk=event.id).exists()
@pytest.mark.django_db
@@ -607,4 +616,5 @@ def test_event_with_order_position_not_delete(token_client, organizer, event, it
assert resp.status_code == 403
assert resp.content.decode() == '{"detail":"The event can not be deleted as it already contains orders. Please ' \
'set \'live\' to false to hide the event and take the shop offline instead."}'
assert organizer.events.filter(pk=event.id).exists()
with scopes_disabled():
assert organizer.events.filter(pk=event.id).exists()

View File

@@ -5,6 +5,7 @@ from unittest import mock
import pytest
from django_countries.fields import Country
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import (
@@ -169,7 +170,8 @@ def test_category_update(token_client, organizer, event, team, category):
format='json'
)
assert resp.status_code == 200
assert ItemCategory.objects.get(pk=category.pk).name == {"en": "Test"}
with scopes_disabled():
assert ItemCategory.objects.get(pk=category.pk).name == {"en": "Test"}
@pytest.mark.django_db
@@ -189,8 +191,9 @@ def test_category_delete(token_client, organizer, event, category3, item):
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/categories/{}/'.format(organizer.slug, event.slug, category3.pk))
assert resp.status_code == 204
assert not event.categories.filter(pk=category3.id).exists()
assert Item.objects.get(pk=item.pk).category is None
with scopes_disabled():
assert not event.categories.filter(pk=category3.id).exists()
assert Item.objects.get(pk=item.pk).category is None
@pytest.fixture
@@ -308,7 +311,8 @@ def test_item_detail(token_client, organizer, event, team, item):
@pytest.mark.django_db
def test_item_detail_variations(token_client, organizer, event, team, item):
var = item.variations.create(value="Children")
with scopes_disabled():
var = item.variations.create(value="Children")
res = dict(TEST_ITEM_RES)
res["id"] = item.pk
res["variations"] = [{
@@ -349,8 +353,9 @@ def test_item_detail_addons(token_client, organizer, event, team, item, category
@pytest.mark.django_db
def test_item_detail_bundles(token_client, organizer, event, team, item, category):
i = event.items.create(name="Included thing", default_price=2)
item.bundles.create(bundled_item=i, count=1, designated_price=2)
with scopes_disabled():
i = event.items.create(name="Included thing", default_price=2)
item.bundles.create(bundled_item=i, count=1, designated_price=2)
res = dict(TEST_ITEM_RES)
res["id"] = item.pk
@@ -398,7 +403,8 @@ def test_item_create(token_client, organizer, event, item, category, taxrule):
format='json'
)
assert resp.status_code == 201
assert Item.objects.get(pk=resp.data['id']).sales_channels == ["web", "pretixpos"]
with scopes_disabled():
assert Item.objects.get(pk=resp.data['id']).sales_channels == ["web", "pretixpos"]
@pytest.mark.django_db
@@ -445,9 +451,10 @@ def test_item_create_with_variation(token_client, organizer, event, item, catego
format='json'
)
assert resp.status_code == 201
new_item = Item.objects.get(pk=resp.data['id'])
assert new_item.variations.first().value.localize('de') == "Kommentar"
assert new_item.variations.first().value.localize('en') == "Comment"
with scopes_disabled():
new_item = Item.objects.get(pk=resp.data['id'])
assert new_item.variations.first().value.localize('de') == "Kommentar"
assert new_item.variations.first().value.localize('en') == "Comment"
@pytest.mark.django_db
@@ -490,10 +497,11 @@ def test_item_create_with_addon(token_client, organizer, event, item, category,
format='json'
)
assert resp.status_code == 201
item = Item.objects.get(pk=resp.data['id'])
assert item.addons.first().addon_category == category
assert item.addons.first().max_count == 10
assert 2 == Item.objects.all().count()
with scopes_disabled():
item = Item.objects.get(pk=resp.data['id'])
assert item.addons.first().addon_category == category
assert item.addons.first().max_count == 10
assert 2 == Item.objects.all().count()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
@@ -534,7 +542,8 @@ def test_item_create_with_addon(token_client, organizer, event, item, category,
)
assert resp.status_code == 400
assert resp.content.decode() == '{"addons":["The add-on\'s category must belong to the same event as the item."]}'
assert 2 == Item.objects.all().count()
with scopes_disabled():
assert 2 == Item.objects.all().count()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
@@ -575,7 +584,8 @@ def test_item_create_with_addon(token_client, organizer, event, item, category,
)
assert resp.status_code == 400
assert resp.content.decode() == '{"addons":["The maximum count needs to be greater than the minimum count."]}'
assert 2 == Item.objects.all().count()
with scopes_disabled():
assert 2 == Item.objects.all().count()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
@@ -619,12 +629,14 @@ def test_item_create_with_addon(token_client, organizer, event, item, category,
'{"addons":["The minimum count needs to be equal to or greater than zero."]}',
'{"addons":[{"min_count":["Ensure this value is greater than or equal to 0."]}]}', # mysql
]
assert 2 == Item.objects.all().count()
with scopes_disabled():
assert 2 == Item.objects.all().count()
@pytest.mark.django_db
def test_item_create_with_bundle(token_client, organizer, event, item, category, item2, taxrule):
i = event.items.create(name="Included thing", default_price=2)
with scopes_disabled():
i = event.items.create(name="Included thing", default_price=2)
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
{
@@ -662,8 +674,9 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category,
format='json'
)
assert resp.status_code == 201
item = Item.objects.get(pk=resp.data['id'])
b = item.bundles.first()
with scopes_disabled():
item = Item.objects.get(pk=resp.data['id'])
b = item.bundles.first()
assert b.bundled_item == i
assert b.bundled_variation is None
assert b.count == 2
@@ -708,7 +721,8 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category,
assert resp.status_code == 400
assert resp.content.decode() == '{"bundles":["The bundled item must belong to the same event as the item."]}'
v = item2.variations.create(value="foo")
with scopes_disabled():
v = item2.variations.create(value="foo")
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug),
{
@@ -760,7 +774,8 @@ def test_item_update(token_client, organizer, event, item, category, item2, cate
format='json'
)
assert resp.status_code == 200
assert Item.objects.get(pk=item.pk).max_per_order == 2
with scopes_disabled():
assert Item.objects.get(pk=item.pk).max_per_order == 2
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug, item.pk),
@@ -896,21 +911,24 @@ def test_item_update_with_addon(token_client, organizer, event, item, category):
def test_items_delete(token_client, organizer, event, item):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug, item.pk))
assert resp.status_code == 204
assert not event.items.filter(pk=item.id).exists()
with scopes_disabled():
assert not event.items.filter(pk=item.id).exists()
@pytest.mark.django_db
def test_items_with_order_position_not_delete(token_client, organizer, event, item, order_position):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug, item.pk))
assert resp.status_code == 403
assert event.items.filter(pk=item.id).exists()
with scopes_disabled():
assert event.items.filter(pk=item.id).exists()
@pytest.mark.django_db
def test_items_with_cart_position_delete(token_client, organizer, event, item, cart_position):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/'.format(organizer.slug, event.slug, item.pk))
assert resp.status_code == 204
assert not event.items.filter(pk=item.id).exists()
with scopes_disabled():
assert not event.items.filter(pk=item.id).exists()
@pytest.fixture
@@ -996,7 +1014,8 @@ def test_variations_create(token_client, organizer, event, item, variation):
format='json'
)
assert resp.status_code == 201
var = ItemVariation.objects.get(pk=resp.data['id'])
with scopes_disabled():
var = ItemVariation.objects.get(pk=resp.data['id'])
assert var.position == 1
assert var.price == 23.0
@@ -1060,40 +1079,47 @@ def test_variations_update(token_client, organizer, event, item, item3, variatio
def test_variations_delete(token_client, organizer, event, item, variations, order):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/variations/{}/'.format(organizer.slug, event.slug, item.pk, variations[0].pk))
assert resp.status_code == 204
assert not item.variations.filter(pk=variations[0].pk).exists()
with scopes_disabled():
assert not item.variations.filter(pk=variations[0].pk).exists()
@pytest.mark.django_db
def test_variations_with_order_position_not_delete(token_client, organizer, event, item, order, variations, order_position):
assert item.variations.filter(pk=variations[0].id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variations[0].id).exists()
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/variations/{}/'.format(organizer.slug, event.slug, item.pk, variations[0].pk))
assert resp.status_code == 403
assert resp.content.decode() == '{"detail":"This variation cannot be deleted because it has already been ordered ' \
'by a user or currently is in a users\'s cart. Please set the variation as ' \
'\'inactive\' instead."}'
assert item.variations.filter(pk=variations[0].id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variations[0].id).exists()
@pytest.mark.django_db
def test_variations_with_cart_position_not_delete(token_client, organizer, event, item, variations, cart_position):
assert item.variations.filter(pk=variations[0].id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variations[0].id).exists()
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/variations/{}/'.format(organizer.slug, event.slug, item.pk, variations[0].pk))
assert resp.status_code == 403
assert resp.content.decode() == '{"detail":"This variation cannot be deleted because it has already been ordered ' \
'by a user or currently is in a users\'s cart. Please set the variation as ' \
'\'inactive\' instead."}'
assert item.variations.filter(pk=variations[0].id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variations[0].id).exists()
@pytest.mark.django_db
def test_only_variation_not_delete(token_client, organizer, event, item, variation):
assert item.variations.filter(pk=variation.id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variation.id).exists()
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/variations/{}/'.format(organizer.slug, event.slug, item.pk, variation.pk))
assert resp.status_code == 403
assert resp.content.decode() == '{"detail":"This variation cannot be deleted because it is the only variation. ' \
'Changing a product with variations to a product without variations is not ' \
'allowed."}'
assert item.variations.filter(pk=variation.id).exists()
with scopes_disabled():
assert item.variations.filter(pk=variation.id).exists()
@pytest.fixture
@@ -1144,7 +1170,8 @@ def test_bundles_create(token_client, organizer, event, item, item2, item3):
format='json'
)
assert resp.status_code == 201
b = ItemBundle.objects.get(pk=resp.data['id'])
with scopes_disabled():
b = ItemBundle.objects.get(pk=resp.data['id'])
assert b.bundled_item == item3
assert b.bundled_variation is None
assert b.designated_price == 1.5
@@ -1176,7 +1203,8 @@ def test_bundles_create(token_client, organizer, event, item, item2, item3):
assert resp.status_code == 400
assert resp.content.decode() == '{"non_field_errors":["The bundled item must not be the same item as the bundling one."]}'
item3.bundles.create(bundled_item=item, count=1, designated_price=3)
with scopes_disabled():
item3.bundles.create(bundled_item=item, count=1, designated_price=3)
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/items/{}/bundles/'.format(organizer.slug, event.slug, item.pk),
{
@@ -1201,7 +1229,8 @@ def test_bundles_update(token_client, organizer, event, item, bundle):
format='json'
)
assert resp.status_code == 200
a = ItemBundle.objects.get(pk=bundle.pk)
with scopes_disabled():
a = ItemBundle.objects.get(pk=bundle.pk)
assert a.count == 3
@@ -1210,7 +1239,8 @@ def test_bundles_delete(token_client, organizer, event, item, bundle):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/bundles/{}/'.format(organizer.slug, event.slug,
item.pk, bundle.pk))
assert resp.status_code == 204
assert not item.bundles.filter(pk=bundle.id).exists()
with scopes_disabled():
assert not item.bundles.filter(pk=bundle.id).exists()
@pytest.fixture
@@ -1270,7 +1300,8 @@ def test_addons_create(token_client, organizer, event, item, category, category2
format='json'
)
assert resp.status_code == 201
addon = ItemAddOn.objects.get(pk=resp.data['id'])
with scopes_disabled():
addon = ItemAddOn.objects.get(pk=resp.data['id'])
assert addon.position == 1
assert addon.addon_category == category
@@ -1315,7 +1346,8 @@ def test_addons_update(token_client, organizer, event, item, addon):
format='json'
)
assert resp.status_code == 200
a = ItemAddOn.objects.get(pk=addon.pk)
with scopes_disabled():
a = ItemAddOn.objects.get(pk=addon.pk)
assert a.min_count == 100
assert a.max_count == 101
@@ -1337,7 +1369,8 @@ def test_addons_delete(token_client, organizer, event, item, addon):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/items/{}/addons/{}/'.format(organizer.slug, event.slug,
item.pk, addon.pk))
assert resp.status_code == 204
assert not item.addons.filter(pk=addon.id).exists()
with scopes_disabled():
assert not item.addons.filter(pk=addon.id).exists()
@pytest.fixture
@@ -1372,7 +1405,8 @@ def test_quota_list(token_client, organizer, event, quota, item, subevent):
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/quotas/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
assert [res] == resp.data['results']
se2 = event.subevents.create(name="Foobar", date_from=datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
with scopes_disabled():
se2 = event.subevents.create(name="Foobar", date_from=datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/quotas/?subevent={}'.format(organizer.slug, event.slug, se2.pk))
assert [] == resp.data['results']
@@ -1404,7 +1438,8 @@ def test_quota_create(token_client, organizer, event, event2, item):
format='json'
)
assert resp.status_code == 201
quota = Quota.objects.get(pk=resp.data['id'])
with scopes_disabled():
quota = Quota.objects.get(pk=resp.data['id'])
assert quota.name == "Ticket Quota"
assert quota.size == 200
@@ -1550,7 +1585,8 @@ def test_quota_update(token_client, organizer, event, quota, item):
format='json'
)
assert resp.status_code == 200
quota = Quota.objects.get(pk=resp.data['id'])
with scopes_disabled():
quota = Quota.objects.get(pk=resp.data['id'])
assert quota.name == "Ticket Quota Update"
assert quota.size == 111
assert quota.all_logentries().count() == 1
@@ -1566,7 +1602,8 @@ def test_quota_update_unchanged(token_client, organizer, event, quota, item):
format='json'
)
assert resp.status_code == 200
quota = Quota.objects.get(pk=resp.data['id'])
with scopes_disabled():
quota = Quota.objects.get(pk=resp.data['id'])
assert quota.size == 200
assert quota.all_logentries().count() == 0
@@ -1575,7 +1612,8 @@ def test_quota_update_unchanged(token_client, organizer, event, quota, item):
def test_quota_delete(token_client, organizer, event, quota):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/quotas/{}/'.format(organizer.slug, event.slug, quota.pk))
assert resp.status_code == 204
assert not event.quotas.filter(pk=quota.id).exists()
with scopes_disabled():
assert not event.quotas.filter(pk=quota.id).exists()
@pytest.mark.django_db
@@ -1690,11 +1728,12 @@ def test_question_create(token_client, organizer, event, event2, item):
format='json'
)
assert resp.status_code == 201
question = Question.objects.get(pk=resp.data['id'])
assert question.question == "What's your name?"
assert question.type == "S"
assert question.identifier is not None
assert len(question.items.all()) == 1
with scopes_disabled():
question = Question.objects.get(pk=resp.data['id'])
assert question.question == "What's your name?"
assert question.type == "S"
assert question.identifier is not None
assert len(question.items.all()) == 1
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/questions/'.format(organizer.slug, event2.slug),
@@ -1784,7 +1823,8 @@ def test_question_create(token_client, organizer, event, event2, item):
format='json'
)
assert resp.status_code == 201
q2 = Question.objects.get(pk=resp.data['id'])
with scopes_disabled():
q2 = Question.objects.get(pk=resp.data['id'])
assert q2.dependency_question == question
@@ -1799,14 +1839,16 @@ def test_question_update(token_client, organizer, event, question):
format='json'
)
assert resp.status_code == 200
question = Question.objects.get(pk=resp.data['id'])
with scopes_disabled():
question = Question.objects.get(pk=resp.data['id'])
assert question.question == "What's your shoe size?"
assert question.type == "N"
@pytest.mark.django_db
def test_question_update_circular_dependency(token_client, organizer, event, question):
q2 = event.questions.create(question="T-Shirt size", type="B", identifier="FOO", dependency_question=question)
with scopes_disabled():
q2 = event.questions.create(question="T-Shirt size", type="B", identifier="FOO", dependency_question=question)
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/questions/{}/'.format(organizer.slug, event.slug, question.pk),
{
@@ -1836,7 +1878,8 @@ def test_question_update_options(token_client, organizer, event, question, item)
def test_question_delete(token_client, organizer, event, question):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/questions/{}/'.format(organizer.slug, event.slug, question.pk))
assert resp.status_code == 204
assert not event.questions.filter(pk=question.id).exists()
with scopes_disabled():
assert not event.questions.filter(pk=question.id).exists()
TEST_OPTIONS_RES = {
@@ -1881,7 +1924,8 @@ def test_options_create(token_client, organizer, event, question):
format='json'
)
assert resp.status_code == 201
option = QuestionOption.objects.get(pk=resp.data['id'])
with scopes_disabled():
option = QuestionOption.objects.get(pk=resp.data['id'])
assert option.answer == "A"
resp = token_client.post(
@@ -1907,7 +1951,8 @@ def test_options_update(token_client, organizer, event, question, option):
format='json'
)
assert resp.status_code == 200
a = QuestionOption.objects.get(pk=option.pk)
with scopes_disabled():
a = QuestionOption.objects.get(pk=option.pk)
assert a.answer == "B"
@@ -1917,7 +1962,8 @@ def test_options_delete(token_client, organizer, event, question, option):
organizer.slug, event.slug, question.pk, option.pk
))
assert resp.status_code == 204
assert not question.options.filter(pk=option.id).exists()
with scopes_disabled():
assert not question.options.filter(pk=option.id).exists()
@pytest.mark.django_db
@@ -1948,11 +1994,12 @@ def test_question_create_with_option(token_client, organizer, event, item):
format='json'
)
assert resp.status_code == 201
question = Question.objects.get(pk=resp.data['id'])
assert str(question.options.first().answer) == "A"
assert question.options.first().identifier is not None
assert str(question.options.last().answer) == "B"
assert 2 == question.options.count()
with scopes_disabled():
question = Question.objects.get(pk=resp.data['id'])
assert str(question.options.first().answer) == "A"
assert question.options.first().identifier is not None
assert str(question.options.last().answer) == "B"
assert 2 == question.options.count()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/questions/'.format(organizer.slug, event.slug),

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ from unittest import mock
import pytest
from django_countries.fields import Country
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import InvoiceAddress, Order, OrderPosition
@@ -159,9 +160,10 @@ def test_subevent_create(token_client, organizer, event, subevent, meta_prop, it
)
assert resp.status_code == 201
assert not subevent.active
assert subevent.meta_values.filter(
property__name=meta_prop.name, value="Workshop"
).exists()
with scopes_disabled():
assert subevent.meta_values.filter(
property__name=meta_prop.name, value="Workshop"
).exists()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
@@ -217,7 +219,8 @@ def test_subevent_create(token_client, organizer, event, subevent, meta_prop, it
)
assert resp.status_code == 201
assert item.default_price == Decimal('23.00')
assert event.subevents.get(id=resp.data['id']).item_price_overrides[item.pk] == Decimal('23.42')
with scopes_disabled():
assert event.subevents.get(id=resp.data['id']).item_price_overrides[item.pk] == Decimal('23.42')
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/subevents/'.format(organizer.slug, event.slug),
@@ -261,7 +264,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
subevent = event.subevents.get(id=subevent.id)
with scopes_disabled():
subevent = event.subevents.get(id=subevent.id)
assert subevent.date_from == datetime(2018, 12, 27, 10, 0, tzinfo=UTC)
assert subevent.date_to == datetime(2018, 12, 28, 10, 0, tzinfo=UTC)
@@ -297,9 +301,10 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert organizer.events.get(slug=event.slug).subevents.get(id=resp.data['id']).meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
with scopes_disabled():
assert organizer.events.get(slug=event.slug).subevents.get(id=resp.data['id']).meta_values.filter(
property__name=meta_prop.name, value="Conference"
).exists()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -310,9 +315,10 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert not subevent.meta_values.filter(
property__name=meta_prop.name
).exists()
with scopes_disabled():
assert not subevent.meta_values.filter(
property__name=meta_prop.name
).exists()
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -339,7 +345,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert subevent.items.get(id=item.pk).default_price == Decimal('23.00')
with scopes_disabled():
assert subevent.items.get(id=item.pk).default_price == Decimal('23.00')
assert subevent.item_price_overrides[item.pk] == Decimal('99.99')
resp = token_client.patch(
@@ -355,7 +362,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('88.88')
with scopes_disabled():
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('88.88')
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -370,7 +378,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
with scopes_disabled():
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -385,7 +394,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('12.34')
with scopes_disabled():
assert event.subevents.get(id=subevent.id).item_price_overrides[item.pk] == Decimal('12.34')
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -395,7 +405,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
with scopes_disabled():
assert item.pk not in event.subevents.get(id=subevent.id).item_price_overrides
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -440,8 +451,9 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert subevent.variations.get(id=variations[0].pk).default_price == Decimal('12.00')
assert subevent.var_price_overrides[variations[0].pk] == Decimal('99.99')
with scopes_disabled():
assert subevent.variations.get(id=variations[0].pk).default_price == Decimal('12.00')
assert subevent.var_price_overrides[variations[0].pk] == Decimal('99.99')
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -456,7 +468,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('88.88')
with scopes_disabled():
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('88.88')
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -471,7 +484,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
with scopes_disabled():
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -486,7 +500,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('12.34')
with scopes_disabled():
assert event.subevents.get(id=subevent.id).var_price_overrides[variations[0].pk] == Decimal('12.34')
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -496,7 +511,8 @@ def test_subevent_update(token_client, organizer, event, subevent, item, item2,
format='json'
)
assert resp.status_code == 200
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
with scopes_disabled():
assert variations[0].pk not in event.subevents.get(id=subevent.id).var_price_overrides
resp = token_client.patch(
'/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug, subevent.pk),
@@ -544,7 +560,8 @@ def test_subevent_delete(token_client, organizer, event, subevent):
resp = token_client.delete('/api/v1/organizers/{}/events/{}/subevents/{}/'.format(organizer.slug, event.slug,
subevent.pk))
assert resp.status_code == 204
assert not event.subevents.filter(pk=subevent.id).exists()
with scopes_disabled():
assert not event.subevents.filter(pk=subevent.id).exists()
@pytest.mark.django_db
@@ -554,4 +571,5 @@ def test_subevent_with_order_position_not_delete(token_client, organizer, event,
assert resp.status_code == 403
assert resp.content.decode() == '{"detail":"The sub-event can not be deleted as it has already been used in ' \
'orders. Please set \'active\' to false instead to hide it from users."}'
assert event.subevents.filter(pk=subevent.id).exists()
with scopes_disabled():
assert event.subevents.filter(pk=subevent.id).exists()

View File

@@ -1,6 +1,7 @@
from decimal import Decimal
import pytest
from django_scopes import scopes_disabled
from pretix.base.models import TaxRule
@@ -80,7 +81,8 @@ def test_rule_delete(token_client, organizer, event, taxrule):
@pytest.mark.django_db
def test_rule_delete_forbidden(token_client, organizer, event, taxrule):
event.items.create(name="Budget Ticket", default_price=23, tax_rule=taxrule)
with scopes_disabled():
event.items.create(name="Budget Ticket", default_price=23, tax_rule=taxrule)
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/taxrules/{}/'.format(organizer.slug, event.slug, taxrule.pk),
)

View File

@@ -5,6 +5,7 @@ from decimal import Decimal
import pytest
from django.utils import timezone
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import Event, Voucher
@@ -58,7 +59,8 @@ def test_voucher_list(token_client, organizer, event, voucher, item, quota, sube
i2 = copy.copy(item)
i2.pk = None
i2.save()
var2 = i2.variations.create(value="foo")
with scopes_disabled():
var2 = i2.variations.create(value="foo")
resp = token_client.get('/api/v1/organizers/{}/events/{}/vouchers/'.format(organizer.slug, event.slug))
assert resp.status_code == 200
@@ -136,9 +138,10 @@ def test_voucher_list(token_client, organizer, event, voucher, item, quota, sube
)
assert [] == resp.data['results']
var = item.variations.create(value='VIP')
voucher.variation = var
voucher.save()
with scopes_disabled():
var = item.variations.create(value='VIP')
voucher.variation = var
voucher.save()
res['variation'] = var.pk
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/vouchers/?variation={}'.format(organizer.slug, event.slug, var.pk)
@@ -208,7 +211,8 @@ def test_voucher_list(token_client, organizer, event, voucher, item, quota, sube
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/vouchers/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
assert [res] == resp.data['results']
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
with scopes_disabled():
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/vouchers/?subevent={}'.format(organizer.slug, event.slug,
se2.pk))
@@ -237,7 +241,8 @@ def create_voucher(token_client, organizer, event, data, expected_failure=False)
assert resp.status_code == 400
else:
assert resp.status_code == 201
return Voucher.objects.get(pk=resp.data['id'])
with scopes_disabled():
return Voucher.objects.get(pk=resp.data['id'])
@pytest.mark.django_db
@@ -324,7 +329,8 @@ def test_create_non_blocking_item_voucher(token_client, organizer, event, item):
@pytest.mark.django_db
def test_create_non_blocking_variation_voucher(token_client, organizer, event, item):
variation = item.variations.create(value="XL")
with scopes_disabled():
variation = item.variations.create(value="XL")
v = create_voucher(
token_client, organizer, event,
data={
@@ -394,7 +400,8 @@ def test_create_blocking_item_voucher_quota_full_invalid(token_client, organizer
@pytest.mark.django_db
def test_create_blocking_variation_voucher_quota_free(token_client, organizer, event, item, quota):
variation = item.variations.create(value="XL")
with scopes_disabled():
variation = item.variations.create(value="XL")
quota.variations.add(variation)
v = create_voucher(
token_client, organizer, event,
@@ -421,7 +428,8 @@ def test_create_short_code(token_client, organizer, event, item):
@pytest.mark.django_db
def test_create_blocking_variation_voucher_quota_full(token_client, organizer, event, item, quota):
variation = item.variations.create(value="XL")
with scopes_disabled():
variation = item.variations.create(value="XL")
quota.variations.add(variation)
quota.size = 0
quota.save()
@@ -463,7 +471,8 @@ def test_create_blocking_quota_voucher_quota_full(token_client, organizer, event
@pytest.mark.django_db
def test_create_duplicate_code(token_client, organizer, event, quota):
v = event.vouchers.create(quota=quota)
with scopes_disabled():
v = event.vouchers.create(quota=quota)
create_voucher(
token_client, organizer, event,
data={
@@ -501,11 +510,12 @@ def test_subevent_required_for_blocking(token_client, organizer, event, item, su
@pytest.mark.django_db
def test_subevent_blocking_quota_free(token_client, organizer, event, item, quota, subevent):
se2 = event.subevents.create(name="Bar", date_from=now())
quota.subevent = subevent
quota.save()
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
q2.items.add(item)
with scopes_disabled():
se2 = event.subevents.create(name="Bar", date_from=now())
quota.subevent = subevent
quota.save()
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
q2.items.add(item)
v = create_voucher(
token_client, organizer, event,
@@ -521,12 +531,13 @@ def test_subevent_blocking_quota_free(token_client, organizer, event, item, quot
@pytest.mark.django_db
def test_subevent_blocking_quota_full(token_client, organizer, event, item, quota, subevent):
se2 = event.subevents.create(name="Bar", date_from=now())
quota.subevent = subevent
quota.size = 0
quota.save()
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
q2.items.add(item)
with scopes_disabled():
se2 = event.subevents.create(name="Bar", date_from=now())
quota.subevent = subevent
quota.size = 0
quota.save()
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
q2.items.add(item)
create_voucher(
token_client, organizer, event,
@@ -553,15 +564,16 @@ def change_voucher(token_client, organizer, event, voucher, data, expected_failu
@pytest.mark.django_db
def test_change_to_item_of_other_event(token_client, organizer, event, item):
e2 = Event.objects.create(
organizer=organizer,
name='Dummy2',
slug='dummy2',
date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC),
plugins='pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf'
)
ticket2 = e2.items.create(name='Late-bird ticket', default_price=23)
v = event.vouchers.create(item=item)
with scopes_disabled():
e2 = Event.objects.create(
organizer=organizer,
name='Dummy2',
slug='dummy2',
date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC),
plugins='pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf'
)
ticket2 = e2.items.create(name='Late-bird ticket', default_price=23)
v = event.vouchers.create(item=item)
change_voucher(
token_client, organizer, event, v,
data={
@@ -575,7 +587,8 @@ def test_change_to_item_of_other_event(token_client, organizer, event, item):
@pytest.mark.django_db
def test_change_non_blocking_voucher(token_client, organizer, event, item, quota):
v = event.vouchers.create(item=item)
with scopes_disabled():
v = event.vouchers.create(item=item)
change_voucher(
token_client, organizer, event, v,
data={
@@ -589,7 +602,8 @@ def test_change_non_blocking_voucher(token_client, organizer, event, item, quota
@pytest.mark.django_db
def test_change_voucher_reduce_max_usages(token_client, organizer, event, item, quota):
v = event.vouchers.create(item=item, max_usages=5, redeemed=3)
with scopes_disabled():
v = event.vouchers.create(item=item, max_usages=5, redeemed=3)
change_voucher(
token_client, organizer, event, v,
data={
@@ -604,7 +618,8 @@ def test_change_voucher_reduce_max_usages(token_client, organizer, event, item,
def test_change_blocking_voucher_unchanged_quota_full(token_client, organizer, event, item, quota):
quota.size = 0
quota.save()
v = event.vouchers.create(item=item, block_quota=True)
with scopes_disabled():
v = event.vouchers.create(item=item, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -620,7 +635,8 @@ def test_change_blocking_voucher_unchanged_quota_full(token_client, organizer, e
def test_change_voucher_to_blocking_quota_full(token_client, organizer, event, item, quota):
quota.size = 0
quota.save()
v = event.vouchers.create(item=item)
with scopes_disabled():
v = event.vouchers.create(item=item)
change_voucher(
token_client, organizer, event, v,
data={
@@ -632,7 +648,8 @@ def test_change_voucher_to_blocking_quota_full(token_client, organizer, event, i
@pytest.mark.django_db
def test_change_voucher_to_blocking_quota_free(token_client, organizer, event, item, quota):
v = event.vouchers.create(item=item)
with scopes_disabled():
v = event.vouchers.create(item=item)
change_voucher(
token_client, organizer, event, v,
data={
@@ -646,8 +663,9 @@ def test_change_voucher_to_blocking_quota_free(token_client, organizer, event, i
def test_change_voucher_validity_to_valid_quota_full(token_client, organizer, event, item, quota):
quota.size = 0
quota.save()
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
with scopes_disabled():
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -660,8 +678,9 @@ def test_change_voucher_validity_to_valid_quota_full(token_client, organizer, ev
@pytest.mark.django_db
def test_change_voucher_validity_to_valid_quota_free(token_client, organizer, event, item, quota):
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
with scopes_disabled():
v = event.vouchers.create(item=item, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -673,9 +692,10 @@ def test_change_voucher_validity_to_valid_quota_free(token_client, organizer, ev
@pytest.mark.django_db
def test_change_item_of_blocking_voucher_quota_free(token_client, organizer, event, item, quota):
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
quota.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
with scopes_disabled():
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
quota.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -687,10 +707,11 @@ def test_change_item_of_blocking_voucher_quota_free(token_client, organizer, eve
@pytest.mark.django_db
def test_change_item_of_blocking_voucher_quota_full(token_client, organizer, event, item, quota):
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
quota2 = event.quotas.create(name='Late', size=0)
quota2.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
with scopes_disabled():
ticket2 = event.items.create(name='Late-bird ticket', default_price=23)
quota2 = event.quotas.create(name='Late', size=0)
quota2.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -702,14 +723,15 @@ def test_change_item_of_blocking_voucher_quota_full(token_client, organizer, eve
@pytest.mark.django_db
def test_change_variation_of_blocking_voucher_quota_free(token_client, organizer, event):
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
qs = event.quotas.create(name='S', size=2)
qs.variations.add(vs)
qm = event.quotas.create(name='M', size=2)
qm.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
with scopes_disabled():
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
qs = event.quotas.create(name='S', size=2)
qs.variations.add(vs)
qm = event.quotas.create(name='M', size=2)
qm.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -721,13 +743,14 @@ def test_change_variation_of_blocking_voucher_quota_free(token_client, organizer
@pytest.mark.django_db
def test_change_variation_of_blocking_voucher_without_quota_change(token_client, organizer, event):
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
q = event.quotas.create(name='S', size=0)
q.variations.add(vs)
q.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
with scopes_disabled():
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
q = event.quotas.create(name='S', size=0)
q.variations.add(vs)
q.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -739,14 +762,15 @@ def test_change_variation_of_blocking_voucher_without_quota_change(token_client,
@pytest.mark.django_db
def test_change_variation_of_blocking_voucher_quota_full(token_client, organizer, event):
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
qs = event.quotas.create(name='S', size=2)
qs.variations.add(vs)
qm = event.quotas.create(name='M', size=0)
qm.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
with scopes_disabled():
shirt = event.items.create(name='Shirt', default_price=23)
vs = shirt.variations.create(value='S')
vm = shirt.variations.create(value='M')
qs = event.quotas.create(name='S', size=2)
qs.variations.add(vs)
qm = event.quotas.create(name='M', size=0)
qm.variations.add(vm)
v = event.vouchers.create(item=shirt, variation=vs, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -758,9 +782,10 @@ def test_change_variation_of_blocking_voucher_quota_full(token_client, organizer
@pytest.mark.django_db
def test_change_quota_of_blocking_voucher_quota_free(token_client, organizer, event):
qs = event.quotas.create(name='S', size=2)
qm = event.quotas.create(name='M', size=2)
v = event.vouchers.create(quota=qs, block_quota=True)
with scopes_disabled():
qs = event.quotas.create(name='S', size=2)
qm = event.quotas.create(name='M', size=2)
v = event.vouchers.create(quota=qs, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -772,9 +797,10 @@ def test_change_quota_of_blocking_voucher_quota_free(token_client, organizer, ev
@pytest.mark.django_db
def test_change_quota_of_blocking_voucher_quota_full(token_client, organizer, event):
qs = event.quotas.create(name='S', size=2)
qm = event.quotas.create(name='M', size=0)
v = event.vouchers.create(quota=qs, block_quota=True)
with scopes_disabled():
qs = event.quotas.create(name='S', size=2)
qm = event.quotas.create(name='M', size=0)
v = event.vouchers.create(quota=qs, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -786,11 +812,12 @@ def test_change_quota_of_blocking_voucher_quota_full(token_client, organizer, ev
@pytest.mark.django_db
def test_change_item_of_blocking_voucher_without_quota_change(token_client, organizer, event, item, quota):
quota.size = 0
quota.save()
ticket2 = event.items.create(name='Standard Ticket', default_price=23)
quota.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
with scopes_disabled():
quota.size = 0
quota.save()
ticket2 = event.items.create(name='Standard Ticket', default_price=23)
quota.items.add(ticket2)
v = event.vouchers.create(item=item, block_quota=True)
change_voucher(
token_client, organizer, event, v,
data={
@@ -802,8 +829,9 @@ def test_change_item_of_blocking_voucher_without_quota_change(token_client, orga
@pytest.mark.django_db
def test_change_code_to_duplicate(token_client, organizer, event, item, quota):
v1 = event.vouchers.create(quota=quota)
v2 = event.vouchers.create(quota=quota)
with scopes_disabled():
v1 = event.vouchers.create(quota=quota)
v2 = event.vouchers.create(quota=quota)
change_voucher(
token_client, organizer, event, v1,
data={
@@ -815,13 +843,14 @@ def test_change_code_to_duplicate(token_client, organizer, event, item, quota):
@pytest.mark.django_db
def test_change_subevent_blocking_quota_free(token_client, organizer, event, item, quota, subevent):
quota.subevent = subevent
quota.save()
se2 = event.subevents.create(name="Bar", date_from=now())
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
q2.items.add(item)
with scopes_disabled():
quota.subevent = subevent
quota.save()
se2 = event.subevents.create(name="Bar", date_from=now())
q2 = event.quotas.create(event=event, name='Tickets', size=5, subevent=se2)
q2.items.add(item)
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
change_voucher(
token_client, organizer, event, v,
data={
@@ -833,13 +862,14 @@ def test_change_subevent_blocking_quota_free(token_client, organizer, event, ite
@pytest.mark.django_db
def test_change_subevent_blocking_quota_full(token_client, organizer, event, item, quota, subevent):
quota.subevent = subevent
quota.save()
se2 = event.subevents.create(name="Bar", date_from=now())
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
q2.items.add(item)
with scopes_disabled():
quota.subevent = subevent
quota.save()
se2 = event.subevents.create(name="Bar", date_from=now())
q2 = event.quotas.create(event=event, name='Tickets', size=0, subevent=se2)
q2.items.add(item)
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
v = event.vouchers.create(item=item, block_quota=True, subevent=subevent)
change_voucher(
token_client, organizer, event, v,
data={
@@ -851,27 +881,32 @@ def test_change_subevent_blocking_quota_full(token_client, organizer, event, ite
@pytest.mark.django_db
def test_delete_voucher(token_client, organizer, event, quota):
v = event.vouchers.create(quota=quota)
with scopes_disabled():
v = event.vouchers.create(quota=quota)
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/vouchers/{}/'.format(organizer.slug, event.slug, v.pk),
)
assert resp.status_code == 204
assert not event.vouchers.filter(pk=v.id).exists()
with scopes_disabled():
assert not event.vouchers.filter(pk=v.id).exists()
@pytest.mark.django_db
def test_delete_voucher_redeemed(token_client, organizer, event, quota):
v = event.vouchers.create(quota=quota, redeemed=1)
with scopes_disabled():
v = event.vouchers.create(quota=quota, redeemed=1)
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/vouchers/{}/'.format(organizer.slug, event.slug, v.pk),
)
assert resp.status_code == 403
assert event.vouchers.filter(pk=v.id).exists()
with scopes_disabled():
assert event.vouchers.filter(pk=v.id).exists()
@pytest.mark.django_db
def test_redeemed_is_not_writable(token_client, organizer, event, item):
v = event.vouchers.create(item=item)
with scopes_disabled():
v = event.vouchers.create(item=item)
change_voucher(
token_client, organizer, event, v,
data={
@@ -919,13 +954,14 @@ def test_create_multiple_vouchers(token_client, organizer, event, item):
], format='json'
)
assert resp.status_code == 201
assert Voucher.objects.count() == 2
assert resp.data[0]['code'] == 'ABCDEFGHI'
v1 = Voucher.objects.get(code='ABCDEFGHI')
assert not v1.block_quota
assert resp.data[1]['code'] == 'JKLMNOPQR'
v2 = Voucher.objects.get(code='JKLMNOPQR')
assert v2.block_quota
with scopes_disabled():
assert Voucher.objects.count() == 2
assert resp.data[0]['code'] == 'ABCDEFGHI'
v1 = Voucher.objects.get(code='ABCDEFGHI')
assert not v1.block_quota
assert resp.data[1]['code'] == 'JKLMNOPQR'
v2 = Voucher.objects.get(code='JKLMNOPQR')
assert v2.block_quota
@pytest.mark.django_db
@@ -967,7 +1003,8 @@ def test_create_multiple_vouchers_one_invalid(token_client, organizer, event, it
)
assert resp.status_code == 400
assert resp.data == [{}, {'code': ['Ensure this field has at least 5 characters.']}]
assert Voucher.objects.count() == 0
with scopes_disabled():
assert Voucher.objects.count() == 0
@pytest.mark.django_db
@@ -1009,4 +1046,5 @@ def test_create_multiple_vouchers_duplicate_code(token_client, organizer, event,
)
assert resp.status_code == 400
assert resp.data == [{}, {'code': ['Duplicate voucher code in request.']}]
assert Voucher.objects.count() == 0
with scopes_disabled():
assert Voucher.objects.count() == 0

View File

@@ -3,6 +3,7 @@ import datetime
from unittest import mock
import pytest
from django_scopes import scopes_disabled
from pytz import UTC
from pretix.base.models import WaitingListEntry
@@ -44,8 +45,9 @@ TEST_WLE_RES = {
@pytest.mark.django_db
def test_wle_list(token_client, organizer, event, wle, item, subevent):
var = item.variations.create(value="Children")
var2 = item.variations.create(value="Children")
with scopes_disabled():
var = item.variations.create(value="Children")
var2 = item.variations.create(value="Children")
res = dict(TEST_WLE_RES)
wle.variation = var
wle.save()
@@ -97,7 +99,8 @@ def test_wle_list(token_client, organizer, event, wle, item, subevent):
'/api/v1/organizers/{}/events/{}/waitinglistentries/?has_voucher=true'.format(organizer.slug, event.slug))
assert [] == resp.data['results']
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
with scopes_disabled():
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
wle.voucher = v
wle.save()
res['voucher'] = v.pk
@@ -112,7 +115,8 @@ def test_wle_list(token_client, organizer, event, wle, item, subevent):
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/waitinglistentries/?subevent={}'.format(organizer.slug, event.slug, subevent.pk))
assert [res] == resp.data['results']
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
with scopes_disabled():
se2 = event.subevents.create(name="Foobar", date_from=datetime.datetime(2017, 12, 27, 10, 0, 0, tzinfo=UTC))
resp = token_client.get(
'/api/v1/organizers/{}/events/{}/waitinglistentries/?subevent={}'.format(organizer.slug, event.slug,
se2.pk))
@@ -136,19 +140,22 @@ def test_delete_wle(token_client, organizer, event, wle, item):
'/api/v1/organizers/{}/events/{}/waitinglistentries/{}/'.format(organizer.slug, event.slug, wle.pk),
)
assert resp.status_code == 204
assert not event.waitinglistentries.filter(pk=wle.id).exists()
with scopes_disabled():
assert not event.waitinglistentries.filter(pk=wle.id).exists()
@pytest.mark.django_db
def test_delete_wle_assigned(token_client, organizer, event, wle, item):
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
with scopes_disabled():
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
wle.voucher = v
wle.save()
resp = token_client.delete(
'/api/v1/organizers/{}/events/{}/waitinglistentries/{}/'.format(organizer.slug, event.slug, wle.pk),
)
assert resp.status_code == 403
assert event.waitinglistentries.filter(pk=wle.id).exists()
with scopes_disabled():
assert event.waitinglistentries.filter(pk=wle.id).exists()
def create_wle(token_client, organizer, event, data, expected_failure=False):
@@ -159,9 +166,9 @@ def create_wle(token_client, organizer, event, data, expected_failure=False):
if expected_failure:
assert resp.status_code == 400
else:
print(resp.data)
assert resp.status_code == 201
return WaitingListEntry.objects.get(pk=resp.data['id'])
with scopes_disabled():
return WaitingListEntry.objects.get(pk=resp.data['id'])
@pytest.mark.django_db
@@ -205,7 +212,8 @@ def test_wle_require_fields(token_client, organizer, event, item, quota):
},
expected_failure=True
)
v = item.variations.create(value="S")
with scopes_disabled():
v = item.variations.create(value="S")
create_wle(
token_client, organizer, event,
data={
@@ -300,7 +308,8 @@ def test_wle_change_email(token_client, organizer, event, item, wle, quota):
@pytest.mark.django_db
def test_wle_change_assigned(token_client, organizer, event, item, wle, quota):
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
with scopes_disabled():
v = event.vouchers.create(item=item, price_mode='set', value=12, tag='Foo')
wle.voucher = v
wle.save()
change_wle(
@@ -315,8 +324,9 @@ def test_wle_change_assigned(token_client, organizer, event, item, wle, quota):
@pytest.mark.django_db
def test_wle_change_to_available_item(token_client, organizer, event, item, wle, quota):
i = event.items.create(name="Budget Ticket", default_price=23)
q = event.quotas.create(name="Budget Ticket", size=1)
with scopes_disabled():
i = event.items.create(name="Budget Ticket", default_price=23)
q = event.quotas.create(name="Budget Ticket", size=1)
q.items.add(i)
change_wle(
token_client, organizer, event, wle,
@@ -330,9 +340,10 @@ def test_wle_change_to_available_item(token_client, organizer, event, item, wle,
@pytest.mark.django_db
def test_wle_change_to_unavailable_item(token_client, organizer, event, item, wle, quota):
i = event.items.create(name="Budget Ticket", default_price=23)
v = i.variations.create(value="S")
q = event.quotas.create(name="Budget Ticket", size=0)
with scopes_disabled():
i = event.items.create(name="Budget Ticket", default_price=23)
v = i.variations.create(value="S")
q = event.quotas.create(name="Budget Ticket", size=0)
q.items.add(i)
q.variations.add(v)
change_wle(
@@ -349,9 +360,10 @@ def test_wle_change_to_unavailable_item(token_client, organizer, event, item, wl
@pytest.mark.django_db
def test_wle_change_to_unavailable_item_missing_var(token_client, organizer, event, item, wle, quota):
i = event.items.create(name="Budget Ticket", default_price=23)
v = i.variations.create(value="S")
q = event.quotas.create(name="Budget Ticket", size=0)
with scopes_disabled():
i = event.items.create(name="Budget Ticket", default_price=23)
v = i.variations.create(value="S")
q = event.quotas.create(name="Budget Ticket", size=0)
q.items.add(i)
q.variations.add(v)
change_wle(

View File

@@ -1,6 +1,7 @@
import copy
import pytest
from django_scopes import scopes_disabled
from pretix.api.models import WebHook
@@ -64,12 +65,13 @@ def test_hook_create(token_client, organizer, event):
format='json'
)
assert resp.status_code == 201
cl = WebHook.objects.get(pk=resp.data['id'])
assert cl.target_url == "https://google.com"
assert cl.limit_events.count() == 1
assert set(cl.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.paid'}
assert not cl.all_events
with scopes_disabled():
cl = WebHook.objects.get(pk=resp.data['id'])
assert cl.target_url == "https://google.com"
assert cl.limit_events.count() == 1
assert set(cl.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.paid'}
assert not cl.all_events
@pytest.mark.django_db
@@ -136,9 +138,10 @@ def test_hook_patch_url(token_client, organizer, event, webhook):
assert resp.status_code == 200
webhook.refresh_from_db()
assert webhook.target_url == "https://pretix.eu"
assert webhook.limit_events.count() == 1
assert set(webhook.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.paid'}
with scopes_disabled():
assert webhook.limit_events.count() == 1
assert set(webhook.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.paid'}
assert webhook.enabled
@@ -153,9 +156,10 @@ def test_hook_patch_types(token_client, organizer, event, webhook):
)
assert resp.status_code == 200
webhook.refresh_from_db()
assert webhook.limit_events.count() == 1
assert set(webhook.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.canceled'}
with scopes_disabled():
assert webhook.limit_events.count() == 1
assert set(webhook.listeners.values_list('action_type', flat=True)) == {'pretix.event.order.placed',
'pretix.event.order.canceled'}
assert webhook.enabled

View File

@@ -6,13 +6,13 @@ class SoupTest(TestCase):
def get_doc(self, *args, **kwargs):
response = self.client.get(*args, **kwargs)
return BeautifulSoup(response.rendered_content, "lxml")
return BeautifulSoup(response.render().content, "lxml")
def post_doc(self, *args, **kwargs):
kwargs['follow'] = True
response = self.client.post(*args, **kwargs)
try:
return BeautifulSoup(response.rendered_content, "lxml")
return BeautifulSoup(response.render().content, "lxml")
except AttributeError:
return BeautifulSoup(response.content, "lxml")

View File

@@ -7,6 +7,7 @@ from django.core.serializers.json import DjangoJSONEncoder
from django.db import DatabaseError, transaction
from django.utils.timezone import now
from django_countries.fields import Country
from django_scopes import scope, scopes_disabled
from pretix.base.models import (
Event, Invoice, InvoiceAddress, Item, ItemVariation, Order, OrderPosition,
@@ -24,72 +25,74 @@ from pretix.base.settings import GlobalSettingsObject
@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'
)
o = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + timedelta(days=10),
total=0, locale='en'
)
tr = event.tax_rules.create(rate=Decimal('19.00'))
o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
tax_value=Decimal('0.05'), tax_rule=tr)
ticket = Item.objects.create(event=event, name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True)
t_shirt = Item.objects.create(event=event, name='T-Shirt',
category=None, default_price=42, tax_rule=tr,
admission=True)
variation = ItemVariation.objects.create(value='M', item=t_shirt)
OrderPosition.objects.create(
order=o,
item=ticket,
variation=None,
price=Decimal("23.00"),
positionid=1,
)
OrderPosition.objects.create(
order=o,
item=t_shirt,
variation=variation,
price=Decimal("42.00"),
positionid=2,
)
OrderPosition.objects.create(
order=o,
item=t_shirt,
variation=variation,
price=Decimal("42.00"),
positionid=3,
canceled=True
)
gs = GlobalSettingsObject()
gs.settings.ecb_rates_date = date.today()
gs.settings.ecb_rates_dict = json.dumps({
"USD": "1.1648",
"RON": "4.5638",
"CZK": "26.024",
"BGN": "1.9558",
"HRK": "7.4098",
"EUR": "1.0000",
"NOK": "9.3525",
"HUF": "305.15",
"DKK": "7.4361",
"PLN": "4.2408",
"GBP": "0.89350",
"SEK": "9.5883"
}, cls=DjangoJSONEncoder)
return event, o
with scope(organizer=o):
event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer'
)
o = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + timedelta(days=10),
total=0, locale='en'
)
tr = event.tax_rules.create(rate=Decimal('19.00'))
o.fees.create(fee_type=OrderFee.FEE_TYPE_PAYMENT, value=Decimal('0.25'), tax_rate=Decimal('19.00'),
tax_value=Decimal('0.05'), tax_rule=tr)
ticket = Item.objects.create(event=event, name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True)
t_shirt = Item.objects.create(event=event, name='T-Shirt',
category=None, default_price=42, tax_rule=tr,
admission=True)
variation = ItemVariation.objects.create(value='M', item=t_shirt)
OrderPosition.objects.create(
order=o,
item=ticket,
variation=None,
price=Decimal("23.00"),
positionid=1,
)
OrderPosition.objects.create(
order=o,
item=t_shirt,
variation=variation,
price=Decimal("42.00"),
positionid=2,
)
OrderPosition.objects.create(
order=o,
item=t_shirt,
variation=variation,
price=Decimal("42.00"),
positionid=3,
canceled=True
)
gs = GlobalSettingsObject()
gs.settings.ecb_rates_date = date.today()
gs.settings.ecb_rates_dict = json.dumps({
"USD": "1.1648",
"RON": "4.5638",
"CZK": "26.024",
"BGN": "1.9558",
"HRK": "7.4098",
"EUR": "1.0000",
"NOK": "9.3525",
"HUF": "305.15",
"DKK": "7.4361",
"PLN": "4.2408",
"GBP": "0.89350",
"SEK": "9.5883"
}, cls=DjangoJSONEncoder)
yield event, o
@pytest.mark.django_db
def test_locale_setting(env):
event, order = env
event.settings.set('invoice_language', 'de')
inv = generate_invoice(order)
with scopes_disabled():
inv = generate_invoice(order)
assert inv.locale == 'de'

View File

@@ -2,6 +2,7 @@ import time
import pytest
from django.utils.timezone import now
from django_scopes import scope, scopes_disabled
from pretix.base.models import Event, Organizer
from pretix.base.services import locking
@@ -17,16 +18,18 @@ def event():
organizer=o, name='Dummy', slug='dummy',
date_from=now()
)
return event
with scope(organizer=o):
yield event
@pytest.mark.django_db
def test_locking_exclusive(event):
with event.lock():
with pytest.raises(LockTimeoutException):
ev = Event.objects.get(id=event.id)
with ev.lock():
pass
with scopes_disabled():
ev = Event.objects.get(id=event.id)
with ev.lock():
pass
@pytest.mark.django_db

View File

@@ -5,6 +5,7 @@ from django.conf import settings
from django.core import mail as djmail
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from django_scopes import scope
from pretix.base.models import Event, Organizer, User
from pretix.base.services.mail import mail
@@ -20,7 +21,8 @@ def env():
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
user.email = 'dummy@dummy.dummy'
user.save()
return event, user, o
with scope(organizer=o):
yield event, user, o
@pytest.mark.django_db

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ import pytest
from django.core import mail as djmail
from django.db import transaction
from django.utils.timezone import now
from django_scopes import scope
from pretix.base.models import (
Event, Item, Order, OrderPosition, Organizer, User,
@@ -18,7 +19,8 @@ def event():
organizer=o, name='Dummy', slug='dummy',
date_from=now()
)
return event
with scope(organizer=o):
yield event
@pytest.fixture

View File

@@ -7,6 +7,7 @@ from django.core import mail as djmail
from django.test import TestCase
from django.utils.timezone import make_aware, now
from django_countries.fields import Country
from django_scopes import scope
from pretix.base.decimal import round_decimal
from pretix.base.models import (
@@ -21,9 +22,10 @@ from pretix.base.services.orders import (
OrderChangeManager, OrderError, _create_order, approve_order, cancel_order,
deny_order, expire_orders, send_download_reminders, send_expiry_warnings,
)
from pretix.testutils.scope import classscope
@pytest.fixture
@pytest.fixture(scope='function')
def event():
o = Organizer.objects.create(name='Dummy', slug='dummy')
event = Event.objects.create(
@@ -31,7 +33,8 @@ def event():
date_from=now(),
plugins='pretix.plugins.banktransfer'
)
return event
with scope(organizer=o):
yield event
@pytest.mark.django_db
@@ -312,42 +315,47 @@ def test_deny(event):
class PaymentReminderTests(TestCase):
def setUp(self):
super().setUp()
o = Organizer.objects.create(name='Dummy', slug='dummy')
self.event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now() + timedelta(days=2),
plugins='pretix.plugins.banktransfer'
)
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now() - timedelta(hours=4),
expires=now() - timedelta(hours=4) + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
djmail.outbox = []
self.o = Organizer.objects.create(name='Dummy', slug='dummy')
with scope(organizer=self.o):
self.event = Event.objects.create(
organizer=self.o, name='Dummy', slug='dummy',
date_from=now() + timedelta(days=2),
plugins='pretix.plugins.banktransfer'
)
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now() - timedelta(hours=4),
expires=now() - timedelta(hours=4) + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
djmail.outbox = []
@classscope(attr='o')
def test_disabled(self):
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_sent_once(self):
self.event.settings.mail_days_order_expire_warning = 12
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_paid(self):
self.order.status = Order.STATUS_PAID
self.order.save()
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_sent_days(self):
self.event.settings.mail_days_order_expire_warning = 9
send_expiry_warnings(sender=self.event)
@@ -356,6 +364,7 @@ class PaymentReminderTests(TestCase):
send_expiry_warnings(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_sent_not_immediately_after_purchase(self):
self.order.datetime = now()
self.order.expires = now() + timedelta(hours=3)
@@ -368,31 +377,34 @@ class PaymentReminderTests(TestCase):
class DownloadReminderTests(TestCase):
def setUp(self):
super().setUp()
o = Organizer.objects.create(name='Dummy', slug='dummy')
self.event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
date_from=now() + timedelta(days=2),
plugins='pretix.plugins.banktransfer'
)
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PAID, locale='en',
datetime=now() - timedelta(hours=4),
expires=now() - timedelta(hours=4) + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={"full_name": "Peter"}, positionid=1
)
djmail.outbox = []
self.o = Organizer.objects.create(name='Dummy', slug='dummy')
with scope(organizer=self.o):
self.event = Event.objects.create(
organizer=self.o, name='Dummy', slug='dummy',
date_from=now() + timedelta(days=2),
plugins='pretix.plugins.banktransfer'
)
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PAID, locale='en',
datetime=now() - timedelta(hours=4),
expires=now() - timedelta(hours=4) + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={"full_name": "Peter"}, positionid=1
)
djmail.outbox = []
@classscope(attr='o')
def test_disabled(self):
send_download_reminders(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_sent_once(self):
self.event.settings.mail_days_download_reminder = 2
send_download_reminders(sender=self.event)
@@ -401,6 +413,7 @@ class DownloadReminderTests(TestCase):
send_download_reminders(sender=self.event)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_send_to_attendees(self):
self.event.settings.mail_send_download_reminder_attendee = True
self.event.settings.mail_days_download_reminder = 2
@@ -413,6 +426,7 @@ class DownloadReminderTests(TestCase):
assert '/ticket/' in djmail.outbox[1].body
assert '/order/' not in djmail.outbox[1].body
@classscope(attr='o')
def test_send_not_to_attendees_with_same_address(self):
self.event.settings.mail_send_download_reminder_attendee = True
self.event.settings.mail_days_download_reminder = 2
@@ -423,6 +437,7 @@ class DownloadReminderTests(TestCase):
assert djmail.outbox[0].to == ['dummy@dummy.test']
assert '/order/' in djmail.outbox[0].body
@classscope(attr='o')
def test_sent_paid_only(self):
self.event.settings.mail_days_download_reminder = 2
self.order.status = Order.STATUS_PENDING
@@ -430,11 +445,13 @@ class DownloadReminderTests(TestCase):
send_download_reminders(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_not_sent_too_early(self):
self.event.settings.mail_days_download_reminder = 1
send_download_reminders(sender=self.event)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_not_sent_too_soon_after_purchase(self):
self.order.datetime = now()
self.order.save()
@@ -446,42 +463,47 @@ class DownloadReminderTests(TestCase):
class OrderCancelTests(TestCase):
def setUp(self):
super().setUp()
o = Organizer.objects.create(name='Dummy', slug='dummy')
self.event = Event.objects.create(organizer=o, name='Dummy', slug='dummy', date_from=now(),
plugins='tests.testdummy')
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now(), expires=now() + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
self.op2 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Dieter"}, positionid=2
)
generate_invoice(self.order)
djmail.outbox = []
self.o = Organizer.objects.create(name='Dummy', slug='dummy')
with scope(organizer=self.o):
self.event = Event.objects.create(organizer=self.o, name='Dummy', slug='dummy', date_from=now(),
plugins='tests.testdummy')
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now(), expires=now() + timedelta(days=10),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
default_price=Decimal('23.00'), admission=True)
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
self.op2 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Dieter"}, positionid=2
)
generate_invoice(self.order)
djmail.outbox = []
@classscope(attr='o')
def test_cancel_canceled(self):
self.order.status = Order.STATUS_CANCELED
self.order.save()
with pytest.raises(OrderError):
cancel_order(self.order.pk)
@classscope(attr='o')
def test_cancel_send_mail(self):
cancel_order(self.order.pk, send_mail=True)
assert len(djmail.outbox) == 1
@classscope(attr='o')
def test_cancel_send_no_mail(self):
cancel_order(self.order.pk, send_mail=False)
assert len(djmail.outbox) == 0
@classscope(attr='o')
def test_cancel_unpaid(self):
cancel_order(self.order.pk)
self.order.refresh_from_db()
@@ -489,6 +511,7 @@ class OrderCancelTests(TestCase):
assert self.order.all_logentries().last().action_type == 'pretix.event.order.canceled'
assert self.order.invoices.count() == 2
@classscope(attr='o')
def test_cancel_unpaid_with_voucher(self):
self.op1.voucher = self.event.vouchers.create(item=self.ticket, redeemed=1)
self.op1.save()
@@ -500,6 +523,7 @@ class OrderCancelTests(TestCase):
assert self.op1.voucher.redeemed == 0
assert self.order.invoices.count() == 2
@classscope(attr='o')
def test_cancel_paid(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -509,6 +533,7 @@ class OrderCancelTests(TestCase):
assert self.order.all_logentries().last().action_type == 'pretix.event.order.canceled'
assert self.order.invoices.count() == 2
@classscope(attr='o')
def test_cancel_paid_with_too_high_fee(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -519,6 +544,7 @@ class OrderCancelTests(TestCase):
assert self.order.status == Order.STATUS_PAID
assert self.order.total == 46
@classscope(attr='o')
def test_cancel_paid_with_fee(self):
f = self.order.fees.create(fee_type=OrderFee.FEE_TYPE_SHIPPING, value=2.5)
self.order.status = Order.STATUS_PAID
@@ -543,6 +569,7 @@ class OrderCancelTests(TestCase):
assert self.order.invoices.count() == 3
assert not self.order.invoices.last().is_cancellation
@classscope(attr='o')
def test_auto_refund_possible(self):
p1 = self.order.payments.create(
amount=Decimal('46.00'),
@@ -558,6 +585,7 @@ class OrderCancelTests(TestCase):
assert self.order.all_logentries().filter(action_type='pretix.event.order.refund.created').exists()
assert not self.order.all_logentries().filter(action_type='pretix.event.order.refund.requested').exists()
@classscope(attr='o')
def test_auto_refund_impossible(self):
self.order.payments.create(
amount=Decimal('46.00'),
@@ -572,39 +600,40 @@ class OrderCancelTests(TestCase):
class OrderChangeManagerTests(TestCase):
def setUp(self):
super().setUp()
o = Organizer.objects.create(name='Dummy', slug='dummy')
self.event = Event.objects.create(organizer=o, name='Dummy', slug='dummy', date_from=now(),
plugins='pretix.plugins.banktransfer')
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now(), expires=now() + timedelta(days=10),
total=Decimal('46.00'),
)
self.order.payments.create(
provider='banktransfer', state=OrderPayment.PAYMENT_STATE_CREATED, amount=self.order.total
)
self.tr7 = self.event.tax_rules.create(rate=Decimal('7.00'))
self.tr19 = self.event.tax_rules.create(rate=Decimal('19.00'))
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rule=self.tr7,
default_price=Decimal('23.00'), admission=True)
self.ticket2 = Item.objects.create(event=self.event, name='Other ticket', tax_rule=self.tr7,
default_price=Decimal('23.00'), admission=True)
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rule=self.tr19,
default_price=Decimal('12.00'))
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
self.op2 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Dieter"}, positionid=2
)
self.ocm = OrderChangeManager(self.order, None)
self.quota = self.event.quotas.create(name='Test', size=None)
self.quota.items.add(self.ticket)
self.quota.items.add(self.ticket2)
self.quota.items.add(self.shirt)
self.o = Organizer.objects.create(name='Dummy', slug='dummy')
with scope(organizer=self.o):
self.event = Event.objects.create(organizer=self.o, name='Dummy', slug='dummy', date_from=now(),
plugins='pretix.plugins.banktransfer')
self.order = Order.objects.create(
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_PENDING, locale='en',
datetime=now(), expires=now() + timedelta(days=10),
total=Decimal('46.00'),
)
self.order.payments.create(
provider='banktransfer', state=OrderPayment.PAYMENT_STATE_CREATED, amount=self.order.total
)
self.tr7 = self.event.tax_rules.create(rate=Decimal('7.00'))
self.tr19 = self.event.tax_rules.create(rate=Decimal('19.00'))
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket', tax_rule=self.tr7,
default_price=Decimal('23.00'), admission=True)
self.ticket2 = Item.objects.create(event=self.event, name='Other ticket', tax_rule=self.tr7,
default_price=Decimal('23.00'), admission=True)
self.shirt = Item.objects.create(event=self.event, name='T-Shirt', tax_rule=self.tr19,
default_price=Decimal('12.00'))
self.op1 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Peter"}, positionid=1
)
self.op2 = OrderPosition.objects.create(
order=self.order, item=self.ticket, variation=None,
price=Decimal("23.00"), attendee_name_parts={'full_name': "Dieter"}, positionid=2
)
self.ocm = OrderChangeManager(self.order, None)
self.quota = self.event.quotas.create(name='Test', size=None)
self.quota.items.add(self.ticket)
self.quota.items.add(self.ticket2)
self.quota.items.add(self.shirt)
def _enable_reverse_charge(self):
self.tr7.eu_reverse_charge = True
@@ -618,6 +647,7 @@ class OrderChangeManagerTests(TestCase):
country=Country('AT')
)
@classscope(attr='o')
def test_multiple_commits_forbidden(self):
self.ocm.change_price(self.op1, Decimal('10.00'))
self.ocm.commit()
@@ -625,6 +655,7 @@ class OrderChangeManagerTests(TestCase):
with self.assertRaises(OrderError):
self.ocm.commit()
@classscope(attr='o')
def test_change_subevent_quota_required(self):
self.event.has_subevents = True
self.event.save()
@@ -637,6 +668,7 @@ class OrderChangeManagerTests(TestCase):
with self.assertRaises(OrderError):
self.ocm.change_subevent(self.op1, se2)
@classscope(attr='o')
def test_change_subevent_success(self):
self.event.has_subevents = True
self.event.save()
@@ -656,6 +688,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.price == Decimal('23.00')
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_change_subevent_with_price_success(self):
self.event.has_subevents = True
self.event.save()
@@ -676,6 +709,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.price == Decimal('12.00')
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_change_subevent_sold_out(self):
self.event.has_subevents = True
self.event.save()
@@ -693,11 +727,13 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.subevent == se1
@classscope(attr='o')
def test_change_item_quota_required(self):
self.quota.delete()
with self.assertRaises(OrderError):
self.ocm.change_item(self.op1, self.shirt, None)
@classscope(attr='o')
def test_change_item_keep_price(self):
p = self.op1.price
self.ocm.change_item(self.op1, self.shirt, None)
@@ -709,6 +745,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.tax_value == Decimal('3.67')
assert self.op1.tax_rule == self.shirt.tax_rule
@classscope(attr='o')
def test_change_item_success(self):
self.ocm.change_item(self.op1, self.shirt, None)
self.ocm.commit()
@@ -720,6 +757,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_change_item_with_price_success(self):
self.ocm.change_item(self.op1, self.shirt, None)
self.ocm.change_price(self.op1, Decimal('12.00'))
@@ -732,6 +770,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_change_price_success(self):
self.ocm.change_price(self.op1, Decimal('24.00'))
self.ocm.commit()
@@ -742,6 +781,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_change_price_net_success(self):
self.tr7.price_includes_tax = False
self.tr7.save()
@@ -754,6 +794,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value
assert self.order.total == self.op1.price + self.op2.price
@classscope(attr='o')
def test_cancel_success(self):
self.ocm.cancel(self.op1)
self.ocm.commit()
@@ -763,6 +804,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.canceled
@classscope(attr='o')
def test_cancel_with_addon(self):
self.shirt.category = self.event.categories.create(name='Add-ons', is_addon=True)
self.ticket.addons.create(addon_category=self.shirt.category)
@@ -781,6 +823,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.canceled
assert self.op1.addons.first().canceled
@classscope(attr='o')
def test_free_to_paid(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -796,6 +839,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.price == Decimal('24.00')
assert self.order.status == Order.STATUS_PENDING
@classscope(attr='o')
def test_cancel_all_in_order(self):
self.ocm.cancel(self.op1)
self.ocm.cancel(self.op2)
@@ -803,9 +847,11 @@ class OrderChangeManagerTests(TestCase):
self.ocm.commit()
assert self.order.positions.count() == 2
@classscope(attr='o')
def test_empty(self):
self.ocm.commit()
@classscope(attr='o')
def test_quota_unlimited(self):
q = self.event.quotas.create(name='Test', size=None)
q.items.add(self.shirt)
@@ -814,6 +860,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.shirt
@classscope(attr='o')
def test_quota_full(self):
q = self.event.quotas.create(name='Test', size=0)
q.items.add(self.shirt)
@@ -823,6 +870,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.ticket
@classscope(attr='o')
def test_quota_ignore(self):
q = self.event.quotas.create(name='Test', size=0)
q.items.add(self.shirt)
@@ -831,6 +879,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.shirt
@classscope(attr='o')
def test_quota_full_but_in_same(self):
q = self.event.quotas.create(name='Test', size=0)
q.items.add(self.shirt)
@@ -840,6 +889,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.shirt
@classscope(attr='o')
def test_multiple_quotas_shared_full(self):
q1 = self.event.quotas.create(name='Test', size=0)
q2 = self.event.quotas.create(name='Test', size=2)
@@ -851,6 +901,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.shirt
@classscope(attr='o')
def test_multiple_quotas_unshared_full(self):
q1 = self.event.quotas.create(name='Test', size=2)
q2 = self.event.quotas.create(name='Test', size=0)
@@ -863,6 +914,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.ticket
@classscope(attr='o')
def test_multiple_items_success(self):
q1 = self.event.quotas.create(name='Test', size=2)
q1.items.add(self.shirt)
@@ -874,6 +926,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.item == self.shirt
assert self.op2.item == self.shirt
@classscope(attr='o')
def test_multiple_items_quotas_partially_full(self):
q1 = self.event.quotas.create(name='Test', size=1)
q1.items.add(self.shirt)
@@ -886,6 +939,7 @@ class OrderChangeManagerTests(TestCase):
assert self.op1.item == self.ticket
assert self.op2.item == self.ticket
@classscope(attr='o')
def test_payment_fee_calculation(self):
self.event.settings.set('tax_rate_default', self.tr19.pk)
prov = self.ocm._get_payment_provider()
@@ -899,6 +953,7 @@ class OrderChangeManagerTests(TestCase):
assert fee.tax_rate == Decimal('19.00')
assert round_decimal(fee.value * (1 - 100 / (100 + fee.tax_rate))) == fee.tax_value
@classscope(attr='o')
def test_pending_free_order_stays_pending(self):
self.event.settings.set('tax_rate_default', self.tr19.pk)
self.ocm.change_price(self.op1, Decimal('0.00'))
@@ -914,6 +969,7 @@ class OrderChangeManagerTests(TestCase):
self.order.refresh_from_db()
assert self.order.status == Order.STATUS_PENDING
@classscope(attr='o')
def test_require_pending(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -922,6 +978,7 @@ class OrderChangeManagerTests(TestCase):
self.op1.refresh_from_db()
assert self.op1.item == self.shirt
@classscope(attr='o')
def test_change_price_to_free_marked_as_paid(self):
self.ocm.change_price(self.op1, Decimal('0.00'))
self.ocm.change_price(self.op2, Decimal('0.00'))
@@ -931,6 +988,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.status == Order.STATUS_PAID
assert self.order.payments.last().provider == 'free'
@classscope(attr='o')
def test_change_price_to_free_require_approval(self):
self.order.require_approval = True
self.order.save()
@@ -942,6 +1000,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == 0
assert self.order.status == Order.STATUS_PENDING
@classscope(attr='o')
def test_change_paid_same_price(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -951,6 +1010,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == 46
assert self.order.status == Order.STATUS_PAID
@classscope(attr='o')
def test_change_paid_different_price(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -960,6 +1020,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == Decimal('28.00')
assert self.order.status == Order.STATUS_PAID
@classscope(attr='o')
def test_change_paid_to_pending(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -975,6 +1036,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.pending_sum == Decimal('2.00')
assert self.order.status == Order.STATUS_PENDING
@classscope(attr='o')
def test_change_paid_stays_paid_when_overpaid(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -996,11 +1058,13 @@ class OrderChangeManagerTests(TestCase):
assert self.order.pending_sum == Decimal('0.00')
assert self.order.status == Order.STATUS_PAID
@classscope(attr='o')
def test_add_item_quota_required(self):
self.quota.delete()
with self.assertRaises(OrderError):
self.ocm.add_position(self.shirt, None, None, None)
@classscope(attr='o')
def test_add_item_success(self):
self.ocm.add_position(self.shirt, None, None, None)
self.ocm.commit()
@@ -1014,6 +1078,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == self.op1.price + self.op2.price + nop.price
assert nop.positionid == 3
@classscope(attr='o')
def test_add_item_net_price_success(self):
self.tr19.price_includes_tax = False
self.tr19.save()
@@ -1029,6 +1094,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == self.op1.price + self.op2.price + nop.price
assert nop.positionid == 3
@classscope(attr='o')
def test_add_item_reverse_charge(self):
self._enable_reverse_charge()
self.ocm.add_position(self.shirt, None, None, None)
@@ -1043,6 +1109,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.total == self.op1.price + self.op2.price + nop.price
assert nop.positionid == 3
@classscope(attr='o')
def test_add_item_custom_price(self):
self.ocm.add_position(self.shirt, None, Decimal('13.00'), None)
self.ocm.commit()
@@ -1055,6 +1122,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
assert self.order.total == self.op1.price + self.op2.price + nop.price
@classscope(attr='o')
def test_add_item_custom_price_tax_always_included(self):
self.tr19.price_includes_tax = False
self.tr19.save()
@@ -1069,6 +1137,7 @@ class OrderChangeManagerTests(TestCase):
assert round_decimal(nop.price * (1 - 100 / (100 + self.shirt.tax_rule.rate))) == nop.tax_value
assert self.order.total == self.op1.price + self.op2.price + nop.price
@classscope(attr='o')
def test_add_item_quota_full(self):
q1 = self.event.quotas.create(name='Test', size=0)
q1.items.add(self.shirt)
@@ -1077,6 +1146,7 @@ class OrderChangeManagerTests(TestCase):
self.ocm.commit()
assert self.order.positions.count() == 2
@classscope(attr='o')
def test_add_item_addon(self):
self.shirt.category = self.event.categories.create(name='Add-ons', is_addon=True)
self.ticket.addons.create(addon_category=self.shirt.category)
@@ -1088,6 +1158,7 @@ class OrderChangeManagerTests(TestCase):
assert nop.item == self.shirt
assert nop.addon_to == self.op1
@classscope(attr='o')
def test_add_item_addon_invalid(self):
with self.assertRaises(OrderError):
self.ocm.add_position(self.shirt, None, Decimal('13.00'), self.op1)
@@ -1095,12 +1166,14 @@ class OrderChangeManagerTests(TestCase):
with self.assertRaises(OrderError):
self.ocm.add_position(self.shirt, None, Decimal('13.00'), None)
@classscope(attr='o')
def test_add_item_subevent_required(self):
self.event.has_subevents = True
self.event.save()
with self.assertRaises(OrderError):
self.ocm.add_position(self.ticket, None, None, None)
@classscope(attr='o')
def test_add_item_subevent_price(self):
self.event.has_subevents = True
self.event.save()
@@ -1118,6 +1191,7 @@ class OrderChangeManagerTests(TestCase):
assert nop.price == Decimal('12.00')
assert nop.subevent == se1
@classscope(attr='o')
def test_reissue_invoice(self):
generate_invoice(self.order)
assert self.order.invoices.count() == 1
@@ -1125,6 +1199,7 @@ class OrderChangeManagerTests(TestCase):
self.ocm.commit()
assert self.order.invoices.count() == 3
@classscope(attr='o')
def test_dont_reissue_invoice_on_free_product_changes(self):
self.event.settings.invoice_include_free = False
generate_invoice(self.order)
@@ -1133,6 +1208,7 @@ class OrderChangeManagerTests(TestCase):
self.ocm.commit()
assert self.order.invoices.count() == 1
@classscope(attr='o')
def test_recalculate_reverse_charge(self):
self.event.settings.set('tax_rate_default', self.tr19.pk)
prov = self.ocm._get_payment_provider()
@@ -1179,6 +1255,7 @@ class OrderChangeManagerTests(TestCase):
assert fee.tax_rate == Decimal('19.00')
assert fee.tax_value == Decimal('0.05')
@classscope(attr='o')
def test_split_simple(self):
old_secret = self.op2.secret
self.ocm.split(self.op2)
@@ -1198,6 +1275,7 @@ class OrderChangeManagerTests(TestCase):
assert not self.order.invoices.exists()
assert not o2.invoices.exists()
@classscope(attr='o')
def test_split_require_approval(self):
self.op2.item.require_approval = True
self.op2.item.save()
@@ -1222,6 +1300,7 @@ class OrderChangeManagerTests(TestCase):
assert not self.order.invoices.exists()
assert not o2.invoices.exists()
@classscope(attr='o')
def test_split_pending_payment_fees(self):
# Set payment fees
self.event.settings.set('tax_rate_default', self.tr19.pk)
@@ -1262,6 +1341,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.positions.count() == 1
assert o2.fees.count() == 1
@classscope(attr='o')
def test_split_paid_no_payment_fees(self):
self.order.status = Order.STATUS_PAID
self.order.save()
@@ -1299,6 +1379,7 @@ class OrderChangeManagerTests(TestCase):
assert p.amount == Decimal('23.00')
assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED
@classscope(attr='o')
def test_split_invoice_address(self):
ia = InvoiceAddress.objects.create(
order=self.order, is_business=True, vat_id='ATU1234567', vat_id_validated=True,
@@ -1325,6 +1406,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.invoice_address != ia
assert o2.invoice_address.company == 'Sample'
@classscope(attr='o')
def test_change_price_of_pending_order_with_payment(self):
self.order.status = Order.STATUS_PENDING
self.order.save()
@@ -1337,6 +1419,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.payments.last().state == OrderPayment.PAYMENT_STATE_CANCELED
assert self.order.payments.last().amount == Decimal('46.00')
@classscope(attr='o')
def test_split_reverse_charge(self):
ia = self._enable_reverse_charge()
@@ -1393,6 +1476,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.invoice_address != ia
assert o2.invoice_address.vat_id_validated is True
@classscope(attr='o')
def test_split_other_fees(self):
# Check if reverse charge is active
self.order.fees.create(fee_type=OrderFee.FEE_TYPE_SHIPPING, tax_rule=self.tr19, value=Decimal('2.50'))
@@ -1424,12 +1508,14 @@ class OrderChangeManagerTests(TestCase):
assert o2.positions.first().price == Decimal('23.00')
assert o2.fees.count() == 1
@classscope(attr='o')
def test_split_to_empty(self):
self.ocm.split(self.op1)
self.ocm.split(self.op2)
with self.assertRaises(OrderError):
self.ocm.commit()
@classscope(attr='o')
def test_split_paid_payment_fees(self):
# Set payment fees
self.event.settings.set('tax_rate_default', self.tr19.pk)
@@ -1472,6 +1558,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.total == Decimal('23.00')
assert o2.fees.count() == 0
@classscope(attr='o')
def test_split_invoice(self):
generate_invoice(self.order)
assert self.order.invoices.count() == 1
@@ -1487,6 +1574,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.invoices.count() == 1
assert o2.invoices.last().lines.count() == 1
@classscope(attr='o')
def test_split_to_free_invoice(self):
self.event.settings.invoice_include_free = False
self.ocm.change_price(self.op2, Decimal('0.00'))
@@ -1508,6 +1596,7 @@ class OrderChangeManagerTests(TestCase):
assert self.order.invoices.last().lines.count() == 1
assert o2.invoices.count() == 0
@classscope(attr='o')
def test_split_to_original_free(self):
self.ocm.change_price(self.op2, Decimal('0.00'))
self.ocm.commit()
@@ -1525,6 +1614,7 @@ class OrderChangeManagerTests(TestCase):
assert o2.total == Decimal('23.00')
assert o2.status == Order.STATUS_PENDING
@classscope(attr='o')
def test_split_to_new_free(self):
self.ocm.change_price(self.op2, Decimal('0.00'))
self.ocm.commit()

View File

@@ -4,6 +4,7 @@ from decimal import Decimal
import pytest
import pytz
from django.utils.timezone import now
from django_scopes import scope
from tests.testdummy.payment import DummyPaymentProvider
from pretix.base.models import (
@@ -19,7 +20,8 @@ def event():
organizer=o, name='Dummy', slug='dummy',
date_from=now()
)
return event
with scope(organizer=o):
yield event
@pytest.mark.django_db

View File

@@ -1,6 +1,7 @@
import pytest
from django.test import RequestFactory
from django.utils.timezone import now
from django_scopes import scope
from pretix.base.models import Event, Organizer, Team, User
from pretix.multidomain.middlewares import SessionMiddleware
@@ -8,7 +9,9 @@ from pretix.multidomain.middlewares import SessionMiddleware
@pytest.fixture
def organizer():
return Organizer.objects.create(name='Dummy', slug='dummy')
o = Organizer.objects.create(name='Dummy', slug='dummy')
with scope(organizer=o):
yield o
@pytest.fixture
@@ -251,25 +254,26 @@ def test_list_of_events(event, user, admin, admin_request):
team2.limit_events.add(event)
team3.limit_events.add(event3)
events = list(user.get_events_with_any_permission(request=admin_request))
assert event in events
assert event2 in events
assert event3 in events
assert event4 not in events
with scope(organizer=[event.organizer, orga2]):
events = list(user.get_events_with_any_permission(request=admin_request))
assert event in events
assert event2 in events
assert event3 in events
assert event4 not in events
events = list(user.get_events_with_permission('can_change_event_settings', request=admin_request))
assert event not in events
assert event2 not in events
assert event3 in events
assert event4 not in events
events = list(user.get_events_with_permission('can_change_event_settings', request=admin_request))
assert event not in events
assert event2 not in events
assert event3 in events
assert event4 not in events
assert set(event.get_users_with_any_permission()) == {user}
assert set(event2.get_users_with_any_permission()) == {user}
assert set(event3.get_users_with_any_permission()) == {user}
assert set(event4.get_users_with_any_permission()) == set()
assert set(event.get_users_with_any_permission()) == {user}
assert set(event2.get_users_with_any_permission()) == {user}
assert set(event3.get_users_with_any_permission()) == {user}
assert set(event4.get_users_with_any_permission()) == set()
assert set(event.get_users_with_permission('can_change_event_settings')) == set()
assert set(event2.get_users_with_permission('can_change_event_settings')) == set()
assert set(event3.get_users_with_permission('can_change_event_settings')) == {user}
assert set(event4.get_users_with_permission('can_change_event_settings')) == set()
assert set(event.get_users_with_permission('can_change_orders')) == {user}
assert set(event.get_users_with_permission('can_change_event_settings')) == set()
assert set(event2.get_users_with_permission('can_change_event_settings')) == set()
assert set(event3.get_users_with_permission('can_change_event_settings')) == {user}
assert set(event4.get_users_with_permission('can_change_event_settings')) == set()
assert set(event.get_users_with_permission('can_change_orders')) == {user}

View File

@@ -2,6 +2,7 @@ from datetime import datetime, time
import pytest
import pytz
from django_scopes import scope
from pretix.base.models import Event, Organizer
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
@@ -41,27 +42,28 @@ def test_relative_date_without_time(event):
@pytest.mark.django_db
def test_relative_date_other_base_point(event):
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_start'))
assert rdw.datetime(event) == TOKYO.localize(datetime(2017, 11, 30, 5, 0, 0))
assert rdw.to_string() == 'RELDATE/1/-/presale_start/'
with scope(organizer=event.organizer):
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_start'))
assert rdw.datetime(event) == TOKYO.localize(datetime(2017, 11, 30, 5, 0, 0))
assert rdw.to_string() == 'RELDATE/1/-/presale_start/'
# presale_end is unset, defaults to date_from
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_end'))
assert rdw.datetime(event) == TOKYO.localize(datetime(2017, 12, 26, 5, 0, 0))
assert rdw.to_string() == 'RELDATE/1/-/presale_end/'
# presale_end is unset, defaults to date_from
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_end'))
assert rdw.datetime(event) == TOKYO.localize(datetime(2017, 12, 26, 5, 0, 0))
assert rdw.to_string() == 'RELDATE/1/-/presale_end/'
# subevent base
se = event.subevents.create(name="SE1", date_from=TOKYO.localize(datetime(2017, 11, 27, 5, 0, 0)))
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='date_from'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 26, 5, 0, 0))
# subevent base
se = event.subevents.create(name="SE1", date_from=TOKYO.localize(datetime(2017, 11, 27, 5, 0, 0)))
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='date_from'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 26, 5, 0, 0))
# presale_start is unset on subevent, default to event
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_start'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 30, 5, 0, 0))
# presale_start is unset on subevent, default to event
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_start'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 30, 5, 0, 0))
# presale_end is unset on all, default to date_from of subevent
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_end'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 26, 5, 0, 0))
# presale_end is unset on all, default to date_from of subevent
rdw = RelativeDateWrapper(RelativeDate(days_before=1, time=None, base_date_name='presale_end'))
assert rdw.datetime(se) == TOKYO.localize(datetime(2017, 11, 26, 5, 0, 0))
@pytest.mark.django_db

View File

@@ -1,5 +1,6 @@
from django.test import TestCase
from django.utils.timezone import now
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
from pretix.base import settings
@@ -43,7 +44,8 @@ class SettingsTestCase(TestCase):
sandbox['bar'] = 'baz'
sandbox.baz = 42
self.event = Event.objects.get(id=self.event.id)
with scopes_disabled():
self.event = Event.objects.get(id=self.event.id)
sandbox = SettingsSandbox('testing', 'foo', self.event)
self.assertEqual(sandbox['bar'], 'baz')
self.assertEqual(sandbox.baz, '42')

View File

@@ -6,6 +6,7 @@ from decimal import Decimal
import pytest
from django.core.files.base import ContentFile
from django.utils.timezone import now
from django_scopes import scope
from pretix.base.models import (
CachedCombinedTicket, CachedTicket, Event, InvoiceAddress, Order,
@@ -27,7 +28,8 @@ def event():
organizer=o, name='Dummy', slug='dummy',
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.ticketoutputpdf'
)
return event
with scope(organizer=o):
yield event
@pytest.fixture

View File

@@ -4,6 +4,7 @@ from decimal import Decimal
import pytest
from django.utils.timezone import now
from django_countries.fields import Country
from django_scopes import scope
from pretix.base.models import Event, InvoiceAddress, Organizer, TaxRule
@@ -15,7 +16,8 @@ def event():
organizer=o, name='Dummy', slug='dummy',
date_from=now()
)
return event
with scope(organizer=o):
yield event
@pytest.mark.django_db

View File

@@ -3,6 +3,7 @@ from decimal import Decimal
import pytest
import pytz
from django_scopes import scope
from pretix.base.models import Event, Organizer
from pretix.base.timeline import timeline_for_event
@@ -29,7 +30,8 @@ def event():
date_from=datetime(2017, 10, 22, 12, 0, 0, tzinfo=tz),
date_to=datetime(2017, 10, 23, 23, 0, 0, tzinfo=tz),
)
return event
with scope(organizer=o):
yield event
@pytest.fixture

View File

@@ -3,6 +3,7 @@ from datetime import timedelta
from django.core import mail as djmail
from django.test import TestCase
from django.utils.timezone import now
from django_scopes import scope
from pretix.base.models import (
Event, Item, ItemVariation, Organizer, Quota, Voucher, WaitingListEntry,
@@ -11,28 +12,31 @@ from pretix.base.models.waitinglist import WaitingListException
from pretix.base.services.waitinglist import (
assign_automatically, process_waitinglist,
)
from pretix.testutils.scope import classscope
class WaitingListTestCase(TestCase):
@classmethod
def setUpTestData(cls):
o = Organizer.objects.create(name='Dummy', slug='dummy')
cls.o = Organizer.objects.create(name='Dummy', slug='dummy')
cls.event = Event.objects.create(
organizer=o, name='Dummy', slug='dummy',
organizer=cls.o, name='Dummy', slug='dummy',
date_from=now(), live=True
)
def setUp(self):
djmail.outbox = []
self.quota = Quota.objects.create(name="Test", size=2, event=self.event)
self.item1 = Item.objects.create(event=self.event, name="Ticket", default_price=23,
admission=True)
self.item2 = Item.objects.create(event=self.event, name="T-Shirt", default_price=23)
self.item3 = Item.objects.create(event=self.event, name="Goodie", default_price=23)
self.var1 = ItemVariation.objects.create(item=self.item2, value='S')
self.var2 = ItemVariation.objects.create(item=self.item2, value='M')
self.var3 = ItemVariation.objects.create(item=self.item3, value='Fancy')
with scope(organizer=self.o):
self.quota = Quota.objects.create(name="Test", size=2, event=self.event)
self.item1 = Item.objects.create(event=self.event, name="Ticket", default_price=23,
admission=True)
self.item2 = Item.objects.create(event=self.event, name="T-Shirt", default_price=23)
self.item3 = Item.objects.create(event=self.event, name="Goodie", default_price=23)
self.var1 = ItemVariation.objects.create(item=self.item2, value='S')
self.var2 = ItemVariation.objects.create(item=self.item2, value='M')
self.var3 = ItemVariation.objects.create(item=self.item3, value='Fancy')
@classscope(attr='o')
def test_send_unavailable(self):
self.quota.items.add(self.item1)
self.quota.size = 0
@@ -43,6 +47,7 @@ class WaitingListTestCase(TestCase):
with self.assertRaises(WaitingListException):
wle.send_voucher()
@classscope(attr='o')
def test_send_double(self):
self.quota.variations.add(self.var1)
self.quota.size = 1
@@ -54,6 +59,7 @@ class WaitingListTestCase(TestCase):
with self.assertRaises(WaitingListException):
wle.send_voucher()
@classscope(attr='o')
def test_send_variation(self):
wle = WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo@bar.com'
@@ -72,6 +78,7 @@ class WaitingListTestCase(TestCase):
assert len(djmail.outbox) == 1
assert djmail.outbox[0].to == [wle.email]
@classscope(attr='o')
def test_send_custom_validity(self):
self.event.settings.set('waiting_list_hours', 24)
wle = WaitingListEntry.objects.create(
@@ -83,103 +90,117 @@ class WaitingListTestCase(TestCase):
assert 3600 * 23 < (wle.voucher.valid_until - now()).seconds < 3600 * 24
def test_send_auto(self):
self.quota.variations.add(self.var1)
self.quota.size = 7
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i)
)
with scope(organizer=self.o):
self.quota.variations.add(self.var1)
self.quota.size = 7
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i)
)
assign_automatically.apply(args=(self.event.pk,))
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 3
assert Voucher.objects.count() == 17
assert sorted(list(WaitingListEntry.objects.filter(voucher__isnull=True).values_list('email', flat=True))) == [
'foo7@bar.com', 'foo8@bar.com', 'foo9@bar.com'
]
with scope(organizer=self.o):
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 3
assert Voucher.objects.count() == 17
assert sorted(list(WaitingListEntry.objects.filter(voucher__isnull=True).values_list('email', flat=True))) == [
'foo7@bar.com', 'foo8@bar.com', 'foo9@bar.com'
]
def test_send_auto_respect_priority(self):
self.quota.variations.add(self.var1)
self.quota.size = 7
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i),
priority=i
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i),
priority=i
)
with scope(organizer=self.o):
self.quota.variations.add(self.var1)
self.quota.size = 7
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i),
priority=i
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i),
priority=i
)
assign_automatically.apply(args=(self.event.pk,))
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 3
assert Voucher.objects.count() == 17
assert sorted(list(WaitingListEntry.objects.filter(voucher__isnull=True).values_list('email', flat=True))) == [
'foo0@bar.com', 'foo1@bar.com', 'foo2@bar.com'
]
with scope(organizer=self.o):
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 3
assert Voucher.objects.count() == 17
assert sorted(list(WaitingListEntry.objects.filter(voucher__isnull=True).values_list('email', flat=True))) == [
'foo0@bar.com', 'foo1@bar.com', 'foo2@bar.com'
]
def test_send_auto_quota_infinite(self):
self.quota.variations.add(self.var1)
self.quota.size = None
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i)
)
with scope(organizer=self.o):
self.quota.variations.add(self.var1)
self.quota.size = None
self.quota.save()
for i in range(10):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
WaitingListEntry.objects.create(
event=self.event, item=self.item1, email='bar{}@bar.com'.format(i)
)
assign_automatically.apply(args=(self.event.pk,))
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 10
assert Voucher.objects.count() == 10
with scope(organizer=self.o):
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 10
assert Voucher.objects.count() == 10
def test_send_periodic_event_over(self):
self.event.settings.set('waiting_list_enabled', True)
self.event.settings.set('waiting_list_auto', True)
self.event.presale_end = now() - timedelta(days=1)
self.event.save()
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
with scope(organizer=self.o):
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
process_waitinglist(None)
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 5
assert Voucher.objects.count() == 0
self.event.presale_end = now() + timedelta(days=1)
self.event.save()
with scope(organizer=self.o):
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 5
assert Voucher.objects.count() == 0
self.event.presale_end = now() + timedelta(days=1)
self.event.save()
def test_send_periodic(self):
self.event.settings.set('waiting_list_enabled', True)
self.event.settings.set('waiting_list_auto', True)
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
with scope(organizer=self.o):
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
process_waitinglist(None)
assert Voucher.objects.count() == 5
with scope(organizer=self.o):
assert Voucher.objects.count() == 5
def test_send_periodic_disabled(self):
self.event.settings.set('waiting_list_enabled', True)
self.event.settings.set('waiting_list_auto', False)
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
with scope(organizer=self.o):
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
process_waitinglist(None)
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 5
assert Voucher.objects.count() == 0
with scope(organizer=self.o):
assert WaitingListEntry.objects.filter(voucher__isnull=True).count() == 5
assert Voucher.objects.count() == 0
def test_send_periodic_disabled2(self):
self.event.settings.set('waiting_list_enabled', False)
self.event.settings.set('waiting_list_auto', True)
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
with scope(organizer=self.o):
for i in range(5):
WaitingListEntry.objects.create(
event=self.event, item=self.item2, variation=self.var1, email='foo{}@bar.com'.format(i)
)
process_waitinglist(None)
assert Voucher.objects.count() == 5
with scope(organizer=self.o):
assert Voucher.objects.count() == 5

View File

@@ -6,6 +6,7 @@ import pytest
import responses
from django.db import transaction
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import Event, Item, Order, OrderPosition, Organizer
@@ -83,13 +84,14 @@ def test_webhook_trigger_event_specific(event, order, webhook, monkeypatch_on_co
"code": "FOO",
"action": "pretix.event.order.paid"
}
first = webhook.calls.last()
assert first.webhook == webhook
assert first.target_url == 'https://google.com'
assert first.action_type == 'pretix.event.order.paid'
assert not first.is_retry
assert first.return_code == 200
assert first.success
with scopes_disabled():
first = webhook.calls.last()
assert first.webhook == webhook
assert first.target_url == 'https://google.com'
assert first.action_type == 'pretix.event.order.paid'
assert not first.is_retry
assert first.return_code == 200
assert first.success
@pytest.mark.django_db
@@ -170,8 +172,9 @@ def test_webhook_retry(event, order, webhook, monkeypatch_on_commit):
with transaction.atomic():
order.log_action('pretix.event.order.paid', {})
assert len(responses.calls) == 2
second = webhook.objects.first()
first = webhook.objects.last()
with scopes_disabled():
second = webhook.objects.first()
first = webhook.objects.last()
assert first.webhook == webhook
assert first.target_url == 'https://google.com'

View File

@@ -1,4 +1,7 @@
import inspect
import pytest
from django_scopes import scopes_disabled
from xdist.dsession import DSession
CRASHED_ITEMS = set()
@@ -31,3 +34,16 @@ def pytest_configure(config):
self.sched.check_schedule(node)
DSession.handle_crashitem = _handle_crashitem
@pytest.hookimpl(hookwrapper=True)
def pytest_fixture_setup(fixturedef, request):
"""
This hack automatically disables django-scopes for all fixtures which are not yield fixtures.
This saves us a *lot* of decorcators…
"""
if inspect.isgeneratorfunction(fixturedef.func):
yield
else:
with scopes_disabled():
yield

View File

@@ -239,7 +239,7 @@ class Login2FAFormTest(TestCase):
def test_totp_invalid(self):
response = self.client.get('/control/login/2fa')
assert 'token' in response.rendered_content
assert 'token' in response.content.decode()
d = TOTPDevice.objects.create(user=self.user, name='test')
totp = TOTP(d.bin_key, d.step, d.t0, d.digits, d.drift)
totp.time = time.time()
@@ -251,7 +251,7 @@ class Login2FAFormTest(TestCase):
def test_totp_valid(self):
response = self.client.get('/control/login/2fa')
assert 'token' in response.rendered_content
assert 'token' in response.content.decode()
d = TOTPDevice.objects.create(user=self.user, name='test')
totp = TOTP(d.bin_key, d.step, d.t0, d.digits, d.drift)
totp.time = time.time()
@@ -274,7 +274,7 @@ class Login2FAFormTest(TestCase):
d = U2FDevice.objects.create(user=self.user, name='test', json_data="{}")
response = self.client.get('/control/login/2fa')
assert 'token' in response.rendered_content
assert 'token' in response.content.decode()
response = self.client.post('/control/login/2fa'.format(d.pk), {
'token': '{"response": "true"}'
})
@@ -291,7 +291,7 @@ class Login2FAFormTest(TestCase):
d = U2FDevice.objects.create(user=self.user, name='test', json_data="{}")
response = self.client.get('/control/login/2fa')
assert 'token' in response.rendered_content
assert 'token' in response.content.decode()
response = self.client.post('/control/login/2fa'.format(d.pk), {
'token': '{"response": "true"}'
})

View File

@@ -3,6 +3,7 @@ from decimal import Decimal
import pytest
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import (
Checkin, Event, Item, ItemAddOn, ItemCategory, LogEntry, Order,
@@ -58,12 +59,14 @@ def dashboard_env():
@pytest.mark.django_db
@scopes_disabled()
def test_dashboard(dashboard_env):
c = checkin_widget(dashboard_env[0])
assert '0/2' in c[0]['content']
@pytest.mark.django_db
@scopes_disabled()
def test_dashboard_pending_not_count(dashboard_env):
c = checkin_widget(dashboard_env[0])
order_pending = Order.objects.create(
@@ -83,6 +86,7 @@ def test_dashboard_pending_not_count(dashboard_env):
@pytest.mark.django_db
@scopes_disabled()
def test_dashboard_with_checkin(dashboard_env):
op = OrderPosition.objects.get(
order=dashboard_env[3],
@@ -256,11 +260,13 @@ def test_checkins_list_mixed(client, checkin_list_env, query, expected):
@pytest.mark.django_db
def test_manual_checkins(client, checkin_list_env):
client.login(email='dummy@dummy.dummy', password='dummy')
assert not checkin_list_env[5][3].checkins.exists()
with scopes_disabled():
assert not checkin_list_env[5][3].checkins.exists()
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
'checkin': [checkin_list_env[5][3].pk]
})
assert checkin_list_env[5][3].checkins.exists()
with scopes_disabled():
assert checkin_list_env[5][3].checkins.exists()
assert LogEntry.objects.filter(
action_type='pretix.event.checkin', object_id=checkin_list_env[5][3].order.pk
).exists()
@@ -269,7 +275,8 @@ def test_manual_checkins(client, checkin_list_env):
@pytest.mark.django_db
def test_manual_checkins_revert(client, checkin_list_env):
client.login(email='dummy@dummy.dummy', password='dummy')
assert not checkin_list_env[5][3].checkins.exists()
with scopes_disabled():
assert not checkin_list_env[5][3].checkins.exists()
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
'checkin': [checkin_list_env[5][3].pk]
})
@@ -277,7 +284,8 @@ def test_manual_checkins_revert(client, checkin_list_env):
'checkin': [checkin_list_env[5][3].pk],
'revert': 'true'
})
assert not checkin_list_env[5][3].checkins.exists()
with scopes_disabled():
assert not checkin_list_env[5][3].checkins.exists()
assert LogEntry.objects.filter(
action_type='pretix.event.checkin', object_id=checkin_list_env[5][3].order.pk
).exists()
@@ -381,11 +389,11 @@ def test_checkins_attendee_name_from_addon_available(client, checkin_list_with_a
class CheckinListFormTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
self.orga1 = Organizer.objects.create(name='CCC', slug='ccc')
self.orga2 = Organizer.objects.create(name='MRM', slug='mrm')
self.event1 = Event.objects.create(
organizer=self.orga1, name='30C3', slug='30c3',
date_from=datetime(2013, 12, 26, tzinfo=timezone.utc),
@@ -404,12 +412,14 @@ class CheckinListFormTest(SoupTest):
doc = self.post_doc('/control/event/%s/%s/checkinlists/add' % (self.orga1.slug, self.event1.slug), form_data)
assert doc.select(".alert-success")
self.assertIn("All", doc.select("#page-wrapper table")[0].text)
assert self.event1.checkin_lists.get(
name='All', all_products=True
)
with scopes_disabled():
assert self.event1.checkin_lists.get(
name='All', all_products=True
)
def test_update(self):
cl = self.event1.checkin_lists.create(name='All', all_products=True)
with scopes_disabled():
cl = self.event1.checkin_lists.create(name='All', all_products=True)
doc = self.get_doc('/control/event/%s/%s/checkinlists/%s/change' % (self.orga1.slug, self.event1.slug, cl.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['all_products'] = ''
@@ -419,14 +429,17 @@ class CheckinListFormTest(SoupTest):
assert doc.select(".alert-success")
cl.refresh_from_db()
assert not cl.all_products
assert list(cl.limit_products.all()) == [self.item_ticket]
with scopes_disabled():
assert list(cl.limit_products.all()) == [self.item_ticket]
def test_delete(self):
cl = self.event1.checkin_lists.create(name='All', all_products=True)
with scopes_disabled():
cl = self.event1.checkin_lists.create(name='All', all_products=True)
doc = self.get_doc('/control/event/%s/%s/checkinlists/%s/delete' % (self.orga1.slug, self.event1.slug, cl.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
doc = self.post_doc('/control/event/%s/%s/checkinlists/%s/delete' % (self.orga1.slug, self.event1.slug, cl.id),
form_data)
assert doc.select(".alert-success")
self.assertNotIn("VAT", doc.select("#page-wrapper")[0].text)
assert not self.event1.checkin_lists.exists()
with scopes_disabled():
assert not self.event1.checkin_lists.exists()

View File

@@ -1,5 +1,6 @@
import pytest
from django.utils.timezone import now
from django_scopes import scopes_disabled
from pretix.base.models import Device, Event, Organizer, Team, User
from pretix.base.models.devices import generate_api_token
@@ -40,7 +41,7 @@ def admin_team(organizer):
def test_list_of_devices(event, admin_user, client, device):
client.login(email='dummy@dummy.dummy', password='dummy')
resp = client.get('/control/organizer/dummy/devices')
assert 'Cashdesk' in resp.rendered_content
assert 'Cashdesk' in resp.content.decode()
@pytest.mark.django_db
@@ -50,11 +51,13 @@ def test_create_device(event, admin_user, admin_team, client):
'name': 'Foo',
'limit_events': str(event.pk),
}, follow=True)
d = Device.objects.last()
assert d.name == 'Foo'
assert not d.all_events
assert list(d.limit_events.all()) == [event]
assert d.initialization_token in resp.content.decode()
print(resp.status_code, resp.content)
with scopes_disabled():
d = Device.objects.last()
assert d.name == 'Foo'
assert not d.all_events
assert list(d.limit_events.all()) == [event]
assert d.initialization_token in resp.content.decode()
@pytest.mark.django_db
@@ -67,13 +70,15 @@ def test_update_device(event, admin_user, admin_team, device, client):
device.refresh_from_db()
assert device.name == 'Cashdesk 2'
assert not device.all_events
assert list(device.limit_events.all()) == [event]
with scopes_disabled():
assert list(device.limit_events.all()) == [event]
@pytest.mark.django_db
def test_revoke_device(event, admin_user, admin_team, device, client):
client.login(email='dummy@dummy.dummy', password='dummy')
device.api_token = generate_api_token()
with scopes_disabled():
device.api_token = generate_api_token()
device.initialized = now()
device.save()

View File

@@ -3,6 +3,7 @@ from decimal import Decimal
import pytz
from django.utils.timezone import now
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
from pytz import timezone
from tests.base import SoupTest, extract_form_fields
@@ -15,6 +16,7 @@ from pretix.testutils.mock import mocker_context
class EventsTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
@@ -49,7 +51,8 @@ class EventsTest(SoupTest):
self.assertNotIn("MRMCD14", tabletext)
def test_quick_setup_later(self):
self.event1.quotas.create(name='foo', size=2)
with scopes_disabled():
self.event1.quotas.create(name='foo', size=2)
resp = self.client.get('/control/event/%s/%s/quickstart/' % (self.orga1.slug, self.event1.slug))
self.assertRedirects(resp, '/control/event/%s/%s/' % (self.orga1.slug, self.event1.slug))
@@ -86,18 +89,19 @@ class EventsTest(SoupTest):
assert self.event1.settings.payment_banktransfer__enabled
assert self.event1.settings.get('payment_banktransfer_bank_details', as_type=LazyI18nString).localize('en') == "Foo"
assert 'pretix.plugins.banktransfer' in self.event1.plugins
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 1
q = self.event1.quotas.first()
assert q.name == 'Tickets'
assert q.size == 300
assert q.items.count() == 2
with scopes_disabled():
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 1
q = self.event1.quotas.first()
assert q.name == 'Tickets'
assert q.size == 300
assert q.items.count() == 2
def test_quick_setup_single_quota(self):
doc = self.get_doc('/control/event/%s/%s/quickstart/' % (self.orga1.slug, self.event1.slug))
@@ -132,22 +136,23 @@ class EventsTest(SoupTest):
assert self.event1.settings.payment_banktransfer__enabled
assert self.event1.settings.get('payment_banktransfer_bank_details', as_type=LazyI18nString).localize('en') == "Foo"
assert 'pretix.plugins.banktransfer' in self.event1.plugins
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 2
q = self.event1.quotas.first()
assert q.name == 'Normal ticket'
assert q.size == 100
assert q.items.count() == 1
q = self.event1.quotas.last()
assert q.name == 'Reduced ticket'
assert q.size == 50
assert q.items.count() == 1
with scopes_disabled():
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 2
q = self.event1.quotas.first()
assert q.name == 'Normal ticket'
assert q.size == 100
assert q.items.count() == 1
q = self.event1.quotas.last()
assert q.name == 'Reduced ticket'
assert q.size == 50
assert q.items.count() == 1
def test_quick_setup_dual_quota(self):
doc = self.get_doc('/control/event/%s/%s/quickstart/' % (self.orga1.slug, self.event1.slug))
@@ -182,22 +187,23 @@ class EventsTest(SoupTest):
assert self.event1.settings.payment_banktransfer__enabled
assert self.event1.settings.get('payment_banktransfer_bank_details', as_type=LazyI18nString).localize('en') == "Foo"
assert 'pretix.plugins.banktransfer' in self.event1.plugins
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 3
q = self.event1.quotas.first()
assert q.name == 'Normal ticket'
assert q.size == 100
assert q.items.count() == 1
q = self.event1.quotas.last()
assert q.name == 'Tickets'
assert q.size == 120
assert q.items.count() == 2
with scopes_disabled():
assert self.event1.items.count() == 2
i = self.event1.items.first()
assert str(i.name) == "Normal ticket"
assert i.default_price == Decimal('13.90')
i = self.event1.items.last()
assert str(i.name) == "Reduced ticket"
assert i.default_price == Decimal('13.20')
assert self.event1.quotas.count() == 3
q = self.event1.quotas.first()
assert q.name == 'Normal ticket'
assert q.size == 100
assert q.items.count() == 1
q = self.event1.quotas.last()
assert q.name == 'Tickets'
assert q.size == 120
assert q.items.count() == 2
def test_settings(self):
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
@@ -257,48 +263,52 @@ class EventsTest(SoupTest):
assert self.event1.testmode
def test_testmode_disable(self):
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en', testmode=True
)
o2 = Order.objects.create(
code='FOO2', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
self.event1.testmode = True
self.event1.save()
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en', testmode=True
)
o2 = Order.objects.create(
code='FOO2', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
self.event1.testmode = True
self.event1.save()
self.post_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug),
{'testmode': 'false'})
self.event1.refresh_from_db()
assert not self.event1.testmode
assert Order.objects.filter(pk=o.pk).exists()
assert Order.objects.filter(pk=o2.pk).exists()
with scopes_disabled():
assert Order.objects.filter(pk=o.pk).exists()
assert Order.objects.filter(pk=o2.pk).exists()
def test_testmode_disable_delete(self):
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en', testmode=True
)
o2 = Order.objects.create(
code='FOO2', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
self.event1.testmode = True
self.event1.save()
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en', testmode=True
)
o2 = Order.objects.create(
code='FOO2', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
self.event1.testmode = True
self.event1.save()
self.post_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug),
{'testmode': 'false', 'delete': 'yes'})
self.event1.refresh_from_db()
assert not self.event1.testmode
assert not Order.objects.filter(pk=o.pk).exists()
assert Order.objects.filter(pk=o2.pk).exists()
with scopes_disabled():
assert not Order.objects.filter(pk=o.pk).exists()
assert Order.objects.filter(pk=o2.pk).exists()
def test_live_disable(self):
self.event1.live = True
@@ -309,9 +319,10 @@ class EventsTest(SoupTest):
assert not self.event1.live
def test_live_ok(self):
self.event1.items.create(name='Test', default_price=5)
self.event1.settings.set('payment_banktransfer__enabled', True)
self.event1.quotas.create(name='Test quota')
with scopes_disabled():
self.event1.items.create(name='Test', default_price=5)
self.event1.settings.set('payment_banktransfer__enabled', True)
self.event1.quotas.create(name='Test quota')
doc = self.get_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug))
assert len(doc.select("input[name=live]"))
self.post_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug),
@@ -320,16 +331,18 @@ class EventsTest(SoupTest):
assert self.event1.live
def test_live_dont_require_payment_method_free(self):
self.event1.items.create(name='Test', default_price=0)
self.event1.settings.set('payment_banktransfer__enabled', False)
self.event1.quotas.create(name='Test quota')
with scopes_disabled():
self.event1.items.create(name='Test', default_price=0)
self.event1.settings.set('payment_banktransfer__enabled', False)
self.event1.quotas.create(name='Test quota')
doc = self.get_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug))
assert len(doc.select("input[name=live]"))
def test_live_require_payment_method(self):
self.event1.items.create(name='Test', default_price=5)
self.event1.settings.set('payment_banktransfer__enabled', False)
self.event1.quotas.create(name='Test quota')
with scopes_disabled():
self.event1.items.create(name='Test', default_price=5)
self.event1.settings.set('payment_banktransfer__enabled', False)
self.event1.quotas.create(name='Test quota')
doc = self.get_doc('/control/event/%s/%s/live/' % (self.orga1.slug, self.event1.slug))
assert len(doc.select("input[name=live]")) == 0
@@ -378,7 +391,8 @@ class EventsTest(SoupTest):
self.event1.save(update_fields=['presale_end'])
def test_payment_settings_relative_date_payment_after_presale_end(self):
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
with scopes_disabled():
tr19 = self.event1.tax_rules.create(rate=Decimal('19.00'))
self.event1.presale_end = self.event1.date_from - datetime.timedelta(days=5)
self.event1.save(update_fields=['presale_end'])
doc = self.post_doc('/control/event/%s/%s/settings/payment' % (self.orga1.slug, self.event1.slug), {
@@ -578,23 +592,24 @@ class EventsTest(SoupTest):
'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 Team.objects.filter(limit_events=ev, members=self.user).exists()
with scopes_disabled():
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 Team.objects.filter(limit_events=ev, members=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)
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)
assert ev.tax_rules.filter(rate=Decimal('19.00')).exists()
assert ev.tax_rules.filter(rate=Decimal('19.00')).exists()
def test_create_event_with_subevents_success(self):
doc = self.get_doc('/control/events/add')
@@ -635,20 +650,22 @@ class EventsTest(SoupTest):
'event_wizard-prefix': 'event_wizard',
'copy-copy_from_event': ''
})
ev = Event.objects.get(slug='33c3')
assert ev.has_subevents
assert ev.subevents.count() == 1
with scopes_disabled():
ev = Event.objects.get(slug='33c3')
assert ev.has_subevents
assert ev.subevents.count() == 1
def test_create_event_copy_success(self):
tr = self.event1.tax_rules.create(
rate=19, name="VAT"
)
self.event1.items.create(
name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True
)
self.event1.settings.tax_rate_default = tr
with scopes_disabled():
tr = self.event1.tax_rules.create(
rate=19, name="VAT"
)
self.event1.items.create(
name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True
)
self.event1.settings.tax_rate_default = tr
doc = self.get_doc('/control/events/add')
doc = self.post_doc('/control/events/add', {
@@ -688,34 +705,36 @@ class EventsTest(SoupTest):
'copy-copy_from_event': self.event1.pk
})
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 Team.objects.filter(limit_events=ev, members=self.user).exists()
assert ev.items.count() == 1
with scopes_disabled():
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 Team.objects.filter(limit_events=ev, members=self.user).exists()
assert ev.items.count() == 1
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)
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)
assert ev.tax_rules.filter(rate=Decimal('19.00')).count() == 1
assert ev.tax_rules.filter(rate=Decimal('19.00')).count() == 1
def test_create_event_clone_success(self):
tr = self.event1.tax_rules.create(
rate=19, name="VAT"
)
self.event1.items.create(
name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True
)
with scopes_disabled():
tr = self.event1.tax_rules.create(
rate=19, name="VAT"
)
self.event1.items.create(
name='Early-bird ticket',
category=None, default_price=23, tax_rule=tr,
admission=True
)
self.event1.settings.tax_rate_default = tr
doc = self.get_doc('/control/events/add?clone=' + str(self.event1.pk))
tabletext = doc.select("form")[0].text
@@ -754,24 +773,25 @@ class EventsTest(SoupTest):
assert not doc.select("#id_copy-copy_from_event_1")
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 Team.objects.filter(limit_events=ev, members=self.user).exists()
assert ev.items.count() == 1
with scopes_disabled():
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 Team.objects.filter(limit_events=ev, members=self.user).exists()
assert ev.items.count() == 1
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)
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)
assert ev.tax_rules.filter(rate=Decimal('19.00')).count() == 1
assert ev.tax_rules.filter(rate=Decimal('19.00')).count() == 1
def test_create_event_only_date_from(self):
# date_to, presale_start & presale_end are optional fields
@@ -806,19 +826,20 @@ class EventsTest(SoupTest):
'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 Team.objects.filter(limit_events=ev, members=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
with scopes_disabled():
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 Team.objects.filter(limit_events=ev, members=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
@@ -909,6 +930,7 @@ class EventsTest(SoupTest):
class SubEventsTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
@@ -967,22 +989,23 @@ class SubEventsTest(SoupTest):
'item-%d-price' % self.ticket.pk: '12'
})
assert doc.select(".alert-success")
se = self.event1.subevents.first()
assert str(se.name) == "SE2"
assert se.active
assert se.date_from.isoformat() == "2017-07-01T10:00:00+00:00"
assert se.date_to.isoformat() == "2017-07-01T12:00:00+00:00"
assert str(se.location) == "Hamburg"
assert se.presale_start.isoformat() == "2017-06-20T10:00:00+00:00"
assert not se.presale_end
assert se.quotas.count() == 1
q = se.quotas.last()
assert q.name == "Q1"
assert q.size == 50
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
with scopes_disabled():
se = self.event1.subevents.first()
assert str(se.name) == "SE2"
assert se.active
assert se.date_from.isoformat() == "2017-07-01T10:00:00+00:00"
assert se.date_to.isoformat() == "2017-07-01T12:00:00+00:00"
assert str(se.location) == "Hamburg"
assert se.presale_start.isoformat() == "2017-06-20T10:00:00+00:00"
assert not se.presale_end
assert se.quotas.count() == 1
q = se.quotas.last()
assert q.name == "Q1"
assert q.size == 50
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
def test_modify(self):
doc = self.get_doc('/control/event/ccc/30c3/subevents/%d/' % self.subevent1.pk)
@@ -1022,14 +1045,15 @@ class SubEventsTest(SoupTest):
assert str(se.location) == "Hamburg"
assert se.presale_start.isoformat() == "2017-06-20T10:00:00+00:00"
assert not se.presale_end
assert se.quotas.count() == 1
q = se.quotas.last()
assert q.name == "Q1"
assert q.size == 50
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
with scopes_disabled():
assert se.quotas.count() == 1
q = se.quotas.last()
assert q.name == "Q1"
assert q.size == 50
assert list(q.items.all()) == [self.ticket]
sei = SubEventItem.objects.get(subevent=se, item=self.ticket)
assert sei.price == 12
assert se.checkinlist_set.count() == 1
def test_delete(self):
doc = self.get_doc('/control/event/ccc/30c3/subevents/%d/delete' % self.subevent1.pk)
@@ -1039,30 +1063,34 @@ class SubEventsTest(SoupTest):
# deleting the second event
doc = self.post_doc('/control/event/ccc/30c3/subevents/%d/delete' % self.subevent2.pk, {})
assert doc.select(".alert-success")
assert not SubEvent.objects.filter(pk=self.subevent2.pk).exists()
assert not SubEvent.objects.filter(pk=self.subevent1.pk).exists()
with scopes_disabled():
assert not SubEvent.objects.filter(pk=self.subevent2.pk).exists()
assert not SubEvent.objects.filter(pk=self.subevent1.pk).exists()
def test_delete_with_orders(self):
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.ticket,
subevent=self.subevent1,
price=Decimal("14"),
)
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.ticket,
subevent=self.subevent1,
price=Decimal("14"),
)
doc = self.get_doc('/control/event/ccc/30c3/subevents/%d/delete' % self.subevent1.pk, follow=True)
assert doc.select(".alert-danger")
doc = self.post_doc('/control/event/ccc/30c3/subevents/%d/delete' % self.subevent1.pk, {}, follow=True)
assert doc.select(".alert-danger")
assert self.event1.subevents.filter(pk=self.subevent1.pk).exists()
with scopes_disabled():
assert self.event1.subevents.filter(pk=self.subevent1.pk).exists()
def test_create_bulk(self):
self.event1.subevents.all().delete()
with scopes_disabled():
self.event1.subevents.all().delete()
self.event1.settings.timezone = 'Europe/Berlin'
doc = self.get_doc('/control/event/ccc/30c3/subevents/bulk_add')
@@ -1120,7 +1148,8 @@ class SubEventsTest(SoupTest):
'checkinlist_set-0-limit_products': str(self.ticket.pk),
})
assert doc.select(".alert-success")
ses = list(self.event1.subevents.order_by('date_from'))
with scopes_disabled():
ses = list(self.event1.subevents.order_by('date_from'))
assert len(ses) == 10
assert str(ses[0].name) == "Foo"
@@ -1128,25 +1157,28 @@ class SubEventsTest(SoupTest):
assert ses[0].date_to.isoformat() == "2018-04-03T13:29:31+00:00"
assert not ses[0].presale_start
assert ses[0].presale_end.isoformat() == "2018-04-02T11:29:31+00:00"
assert ses[0].quotas.count() == 1
assert list(ses[0].quotas.first().items.all()) == [self.ticket]
assert SubEventItem.objects.get(subevent=ses[0], item=self.ticket).price == 16
assert ses[0].checkinlist_set.count() == 1
with scopes_disabled():
assert ses[0].quotas.count() == 1
assert list(ses[0].quotas.first().items.all()) == [self.ticket]
assert SubEventItem.objects.get(subevent=ses[0], item=self.ticket).price == 16
assert ses[0].checkinlist_set.count() == 1
assert str(ses[1].name) == "Foo"
assert ses[1].date_from.isoformat() == "2019-04-03T11:29:31+00:00"
assert ses[1].date_to.isoformat() == "2019-04-03T13:29:31+00:00"
assert not ses[1].presale_start
assert ses[1].presale_end.isoformat() == "2019-04-02T11:29:31+00:00"
assert ses[1].quotas.count() == 1
assert list(ses[1].quotas.first().items.all()) == [self.ticket]
assert SubEventItem.objects.get(subevent=ses[0], item=self.ticket).price == 16
assert ses[1].checkinlist_set.count() == 1
with scopes_disabled():
assert ses[1].quotas.count() == 1
assert list(ses[1].quotas.first().items.all()) == [self.ticket]
assert SubEventItem.objects.get(subevent=ses[0], item=self.ticket).price == 16
assert ses[1].checkinlist_set.count() == 1
assert ses[-1].date_from.isoformat() == "2027-04-03T11:29:31+00:00"
def test_create_bulk_daily_interval(self):
self.event1.subevents.all().delete()
with scopes_disabled():
self.event1.subevents.all().delete()
self.event1.settings.timezone = 'Europe/Berlin'
doc = self.get_doc('/control/event/ccc/30c3/subevents/bulk_add')
@@ -1194,7 +1226,8 @@ class SubEventsTest(SoupTest):
'checkinlist_set-MAX_NUM_FORMS': '1000',
})
assert doc.select(".alert-success")
ses = list(self.event1.subevents.order_by('date_from'))
with scopes_disabled():
ses = list(self.event1.subevents.order_by('date_from'))
assert len(ses) == 183
assert ses[0].date_from.isoformat() == "2018-04-03T11:29:31+00:00"
@@ -1202,7 +1235,8 @@ class SubEventsTest(SoupTest):
assert ses[-1].date_from.isoformat() == "2019-04-02T11:29:31+00:00"
def test_create_bulk_exclude(self):
self.event1.subevents.all().delete()
with scopes_disabled():
self.event1.subevents.all().delete()
self.event1.settings.timezone = 'Europe/Berlin'
doc = self.get_doc('/control/event/ccc/30c3/subevents/bulk_add')
@@ -1265,7 +1299,8 @@ class SubEventsTest(SoupTest):
'checkinlist_set-MAX_NUM_FORMS': '1000',
})
assert doc.select(".alert-success")
ses = list(self.event1.subevents.order_by('date_from'))
with scopes_disabled():
ses = list(self.event1.subevents.order_by('date_from'))
assert len(ses) == 314
assert ses[0].date_from.isoformat() == "2018-04-03T11:29:31+00:00"
@@ -1273,7 +1308,8 @@ class SubEventsTest(SoupTest):
assert ses[6].date_from.isoformat() == "2018-04-10T11:29:31+00:00"
def test_create_bulk_monthly_interval(self):
self.event1.subevents.all().delete()
with scopes_disabled():
self.event1.subevents.all().delete()
self.event1.settings.timezone = 'Europe/Berlin'
doc = self.post_doc('/control/event/ccc/30c3/subevents/bulk_add', {
@@ -1320,7 +1356,8 @@ class SubEventsTest(SoupTest):
'checkinlist_set-MAX_NUM_FORMS': '1000',
})
assert doc.select(".alert-success")
ses = list(self.event1.subevents.order_by('date_from'))
with scopes_disabled():
ses = list(self.event1.subevents.order_by('date_from'))
assert len(ses) == 12
assert ses[0].date_from.isoformat() == "2018-04-30T11:29:31+00:00"
@@ -1328,7 +1365,8 @@ class SubEventsTest(SoupTest):
assert ses[-1].date_from.isoformat() == "2019-03-29T12:29:31+00:00"
def test_create_bulk_weekly_interval(self):
self.event1.subevents.all().delete()
with scopes_disabled():
self.event1.subevents.all().delete()
self.event1.settings.timezone = 'Europe/Berlin'
doc = self.post_doc('/control/event/ccc/30c3/subevents/bulk_add', {
@@ -1375,7 +1413,8 @@ class SubEventsTest(SoupTest):
'checkinlist_set-MAX_NUM_FORMS': '1000',
})
assert doc.select(".alert-success")
ses = list(self.event1.subevents.order_by('date_from'))
with scopes_disabled():
ses = list(self.event1.subevents.order_by('date_from'))
assert len(ses) == 52
assert ses[0].date_from.isoformat() == "2018-04-05T11:29:31+00:00"
@@ -1385,25 +1424,27 @@ class SubEventsTest(SoupTest):
def test_delete_bulk(self):
self.subevent2.active = True
self.subevent2.save()
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.ticket,
subevent=self.subevent1,
price=Decimal("14"),
)
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.ticket,
subevent=self.subevent1,
price=Decimal("14"),
)
doc = self.post_doc('/control/event/ccc/30c3/subevents/bulk_action', {
'subevent': [str(self.subevent1.pk), str(self.subevent2.pk)],
'action': 'delete_confirm'
}, follow=True)
assert doc.select(".alert-success")
assert not self.event1.subevents.filter(pk=self.subevent2.pk).exists()
assert self.event1.subevents.get(pk=self.subevent1.pk).active is False
with scopes_disabled():
assert not self.event1.subevents.filter(pk=self.subevent2.pk).exists()
assert self.event1.subevents.get(pk=self.subevent1.pk).active is False
def test_disable_bulk(self):
self.subevent2.active = True
@@ -1413,7 +1454,8 @@ class SubEventsTest(SoupTest):
'action': 'disable'
}, follow=True)
assert doc.select(".alert-success")
assert self.event1.subevents.get(pk=self.subevent2.pk).active is False
with scopes_disabled():
assert self.event1.subevents.get(pk=self.subevent2.pk).active is False
def test_enable_bulk(self):
self.subevent2.active = False
@@ -1423,10 +1465,12 @@ class SubEventsTest(SoupTest):
'action': 'enable'
}, follow=True)
assert doc.select(".alert-success")
assert self.event1.subevents.get(pk=self.subevent2.pk).active is True
with scopes_disabled():
assert self.event1.subevents.get(pk=self.subevent2.pk).active is True
class EventDeletionTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
@@ -1454,21 +1498,24 @@ class EventDeletionTest(SoupTest):
'slug': '30c3'
})
assert not self.orga1.events.exists()
with scopes_disabled():
assert not self.orga1.events.exists()
def test_delete_wrong_slug(self):
self.post_doc('/control/event/ccc/30c3/delete/', {
'user_pw': 'dummy',
'slug': '31c3'
})
assert self.orga1.events.exists()
with scopes_disabled():
assert self.orga1.events.exists()
def test_delete_wrong_pw(self):
self.post_doc('/control/event/ccc/30c3/delete/', {
'user_pw': 'invalid',
'slug': '30c3'
})
assert self.orga1.events.exists()
with scopes_disabled():
assert self.orga1.events.exists()
def test_delete_orders(self):
Order.objects.create(
@@ -1481,4 +1528,5 @@ class EventDeletionTest(SoupTest):
'user_pw': 'dummy',
'slug': '30c3'
})
assert self.orga1.events.exists()
with scopes_disabled():
assert self.orga1.events.exists()

View File

@@ -2,6 +2,7 @@ import datetime
from decimal import Decimal
from django.utils.timezone import now
from django_scopes import scopes_disabled
from tests.base import SoupTest, extract_form_fields
from pretix.base.models import (
@@ -11,6 +12,7 @@ from pretix.base.models import (
class ItemFormTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
@@ -47,11 +49,13 @@ class CategoriesTest(ItemFormTest):
assert doc.select(".alert-success")
self.assertIn("T-Shirts", doc.select("#page-wrapper table")[0].text)
self.assertNotIn("Entry tickets", doc.select("#page-wrapper table")[0].text)
assert str(ItemCategory.objects.get(id=c.id).name) == 'T-Shirts'
with scopes_disabled():
assert str(ItemCategory.objects.get(id=c.id).name) == 'T-Shirts'
def test_sort(self):
c1 = ItemCategory.objects.create(event=self.event1, name="Entry tickets", position=0)
ItemCategory.objects.create(event=self.event1, name="T-Shirts", position=1)
with scopes_disabled():
c1 = ItemCategory.objects.create(event=self.event1, name="Entry tickets", position=0)
ItemCategory.objects.create(event=self.event1, name="T-Shirts", position=1)
doc = self.get_doc('/control/event/%s/%s/categories/' % (self.orga1.slug, self.event1.slug))
self.assertIn("Entry tickets", doc.select("table > tbody > tr")[0].text)
self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text)
@@ -67,14 +71,16 @@ class CategoriesTest(ItemFormTest):
self.assertIn("T-Shirts", doc.select("table > tbody > tr")[1].text)
def test_delete(self):
c = ItemCategory.objects.create(event=self.event1, name="Entry tickets")
with scopes_disabled():
c = ItemCategory.objects.create(event=self.event1, name="Entry tickets")
doc = self.get_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
doc = self.post_doc('/control/event/%s/%s/categories/%s/delete' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
assert doc.select(".alert-success")
self.assertNotIn("Entry tickets", doc.select("#page-wrapper")[0].text)
assert not ItemCategory.objects.filter(id=c.id).exists()
with scopes_disabled():
assert not ItemCategory.objects.filter(id=c.id).exists()
class QuestionsTest(ItemFormTest):
@@ -90,8 +96,9 @@ class QuestionsTest(ItemFormTest):
self.assertIn("shoe size", doc.select("#page-wrapper table")[0].text)
def test_update_choices(self):
c = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = c.options.create(answer='Germany')
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = c.options.create(answer='Germany')
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['form-TOTAL_FORMS'] = '1'
@@ -104,12 +111,14 @@ class QuestionsTest(ItemFormTest):
self.post_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
c.refresh_from_db()
assert c.options.exists()
assert str(c.options.first().answer) == 'England'
with scopes_disabled():
assert c.options.exists()
assert str(c.options.first().answer) == 'England'
def test_delete_choices(self):
c = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = c.options.create(answer='Germany')
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = c.options.create(answer='Germany')
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['form-TOTAL_FORMS'] = '1'
@@ -123,10 +132,12 @@ class QuestionsTest(ItemFormTest):
self.post_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
c.refresh_from_db()
assert not c.options.exists()
with scopes_disabled():
assert not c.options.exists()
def test_add_choices(self):
c = Question.objects.create(event=self.event1, question="What country are you from?", type="N", required=True)
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What country are you from?", type="N", required=True)
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['type'] = 'C'
@@ -139,12 +150,14 @@ class QuestionsTest(ItemFormTest):
form_data['form-0-answer_0'] = 'Germany'
self.post_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
c = Question.objects.get(id=c.id)
assert c.options.exists()
assert str(c.options.first().answer) == 'Germany'
with scopes_disabled():
c = Question.objects.get(id=c.id)
assert c.options.exists()
assert str(c.options.first().answer) == 'Germany'
def test_update(self):
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['items'] = self.item1.id
@@ -153,13 +166,15 @@ class QuestionsTest(ItemFormTest):
form_data)
self.assertIn("How old", doc.select("#page-wrapper table")[0].text)
self.assertNotIn("shoe size", doc.select("#page-wrapper table")[0].text)
c = Question.objects.get(id=c.id)
self.assertTrue(c.required)
assert str(Question.objects.get(id=c.id).question) == 'How old are you?'
with scopes_disabled():
c = Question.objects.get(id=c.id)
self.assertTrue(c.required)
assert str(Question.objects.get(id=c.id).question) == 'How old are you?'
def test_sort(self):
q1 = Question.objects.create(event=self.event1, question="Vegetarian?", type="N", required=True, position=0)
Question.objects.create(event=self.event1, question="Food allergies?", position=1)
with scopes_disabled():
q1 = Question.objects.create(event=self.event1, question="Vegetarian?", type="N", required=True, position=0)
Question.objects.create(event=self.event1, question="Food allergies?", position=1)
doc = self.get_doc('/control/event/%s/%s/questions/' % (self.orga1.slug, self.event1.slug))
self.assertIn("Vegetarian?", doc.select("table > tbody > tr")[0].text)
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[1].text)
@@ -175,32 +190,35 @@ class QuestionsTest(ItemFormTest):
self.assertIn("Food allergies?", doc.select("table > tbody > tr")[1].text)
def test_delete(self):
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
doc = self.get_doc('/control/event/%s/%s/questions/%s/delete' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
doc = self.post_doc('/control/event/%s/%s/questions/%s/delete' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
assert doc.select(".alert-success")
self.assertNotIn("shoe size", doc.select("#page-wrapper")[0].text)
assert not Question.objects.filter(id=c.id).exists()
with scopes_disabled():
assert not Question.objects.filter(id=c.id).exists()
def test_question_view(self):
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
with scopes_disabled():
c = Question.objects.create(event=self.event1, question="What is your shoe size?", type="N", required=True)
item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0, position=1)
o = Order.objects.create(code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING, datetime=now(),
expires=now() + datetime.timedelta(days=10),
total=14, locale='en')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Peter"})
op.answers.create(question=c, answer='42')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Michael"})
op.answers.create(question=c, answer='42')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Petra"})
op.answers.create(question=c, answer='39')
item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0, position=1)
o = Order.objects.create(code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING, datetime=now(),
expires=now() + datetime.timedelta(days=10),
total=14, locale='en')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Peter"})
op.answers.create(question=c, answer='42')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Michael"})
op.answers.create(question=c, answer='42')
op = OrderPosition.objects.create(order=o, item=item1, variation=None, price=Decimal("14"),
attendee_name_parts={'full_name': "Petra"})
op.answers.create(question=c, answer='39')
doc = self.get_doc('/control/event/%s/%s/questions/%s/' % (self.orga1.slug, self.event1.slug, c.id))
tbl = doc.select('.container-fluid table.table-bordered tbody')[0]
@@ -219,9 +237,10 @@ class QuestionsTest(ItemFormTest):
assert tbl.select('tr')[0].select('td')[0].text.strip() == '42'
def test_set_dependency(self):
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="T", required=True)
o1 = q1.options.create(answer='Germany')
with scopes_disabled():
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="T", required=True)
o1 = q1.options.create(answer='Germany')
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, q2.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['items'] = self.item1.id
@@ -235,10 +254,11 @@ class QuestionsTest(ItemFormTest):
assert q2.dependency_value == o1.identifier
def test_set_dependency_circular(self):
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = q1.options.create(answer='Germany')
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="C", required=True,
dependency_question=q1, dependency_value=o1.identifier)
with scopes_disabled():
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
o1 = q1.options.create(answer='Germany')
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="C", required=True,
dependency_question=q1, dependency_value=o1.identifier)
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, q1.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['dependency_question'] = q2.pk
@@ -248,8 +268,9 @@ class QuestionsTest(ItemFormTest):
assert not doc.select(".alert-success")
def test_set_dependency_to_non_choice(self):
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="N", required=True)
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="T", required=True)
with scopes_disabled():
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="N", required=True)
q2 = Question.objects.create(event=self.event1, question="What city are you from?", type="T", required=True)
doc = self.get_doc('/control/event/%s/%s/questions/%s/change' % (self.orga1.slug, self.event1.slug, q2.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['dependency_question'] = q1.pk
@@ -271,11 +292,12 @@ class QuotaTest(ItemFormTest):
self.assertIn("Full house", doc.select("#page-wrapper table")[0].text)
def test_update(self):
c = Quota.objects.create(event=self.event1, name="Full house", size=500)
item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0)
item2 = Item.objects.create(event=self.event1, name="Business", default_price=0)
ItemVariation.objects.create(item=item2, value="Silver")
ItemVariation.objects.create(item=item2, value="Gold")
with scopes_disabled():
c = Quota.objects.create(event=self.event1, name="Full house", size=500)
item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0)
item2 = Item.objects.create(event=self.event1, name="Business", default_price=0)
ItemVariation.objects.create(item=item2, value="Silver")
ItemVariation.objects.create(item=item2, value="Gold")
doc = self.get_doc('/control/event/%s/%s/quotas/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
[i for i in doc.select('[name=itemvars]') if i.get('value') == str(item1.id)][0]['checked'] = 'checked'
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
@@ -285,35 +307,41 @@ class QuotaTest(ItemFormTest):
doc = self.get_doc('/control/event/%s/%s/quotas/' % (self.orga1.slug, self.event1.slug))
self.assertIn("350", doc.select("#page-wrapper table")[0].text)
self.assertNotIn("500", doc.select("#page-wrapper table")[0].text)
assert Quota.objects.get(id=c.id).size == 350
assert item1 in Quota.objects.get(id=c.id).items.all()
with scopes_disabled():
assert Quota.objects.get(id=c.id).size == 350
assert item1 in Quota.objects.get(id=c.id).items.all()
def test_update_subevent(self):
self.event1.has_subevents = True
self.event1.save()
se1 = self.event1.subevents.create(name="Foo", date_from=now())
se2 = self.event1.subevents.create(name="Bar", date_from=now())
c = Quota.objects.create(event=self.event1, name="Full house", size=500, subevent=se1)
with scopes_disabled():
se1 = self.event1.subevents.create(name="Foo", date_from=now())
se2 = self.event1.subevents.create(name="Bar", date_from=now())
c = Quota.objects.create(event=self.event1, name="Full house", size=500, subevent=se1)
doc = self.get_doc('/control/event/%s/%s/quotas/%s/change' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
form_data['subevent'] = se2.pk
self.post_doc('/control/event/%s/%s/quotas/%s/change' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
assert Quota.objects.get(id=c.id).subevent == se2
with scopes_disabled():
assert Quota.objects.get(id=c.id).subevent == se2
def test_delete(self):
c = Quota.objects.create(event=self.event1, name="Full house", size=500)
with scopes_disabled():
c = Quota.objects.create(event=self.event1, name="Full house", size=500)
doc = self.get_doc('/control/event/%s/%s/quotas/%s/delete' % (self.orga1.slug, self.event1.slug, c.id))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
doc = self.post_doc('/control/event/%s/%s/quotas/%s/delete' % (self.orga1.slug, self.event1.slug, c.id),
form_data)
assert doc.select(".alert-success")
self.assertNotIn("Full house", doc.select("#page-wrapper")[0].text)
assert not Quota.objects.filter(id=c.id).exists()
with scopes_disabled():
assert not Quota.objects.filter(id=c.id).exists()
class ItemsTest(ItemFormTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.item2 = Item.objects.create(event=self.event1, name="Business", default_price=0, position=2,
@@ -341,7 +369,7 @@ class ItemsTest(ItemFormTest):
'tax_rate': '19.00'
})
resp = self.client.get('/control/event/%s/%s/items/' % (self.orga1.slug, self.event1.slug))
assert 'T-Shirt' in resp.rendered_content
assert 'T-Shirt' in resp.content.decode()
def test_update(self):
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item1.id), {
@@ -366,20 +394,23 @@ class ItemsTest(ItemFormTest):
'form-0-min_count': '1',
'form-0-max_count': '2',
})
assert self.item2.addons.exists()
assert self.item2.addons.first().addon_category == self.addoncat
with scopes_disabled():
assert self.item2.addons.exists()
assert self.item2.addons.first().addon_category == self.addoncat
a = self.item2.addons.first()
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': str(self.item2.addons.first().pk),
'form-0-id': str(a.pk),
'form-0-addon_category': str(self.addoncat.pk),
'form-0-min_count': '1',
'form-0-max_count': '2',
'form-0-DELETE': 'on',
})
assert not self.item2.addons.exists()
with scopes_disabled():
assert not self.item2.addons.exists()
# Do not allow duplicates
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
@@ -396,7 +427,8 @@ class ItemsTest(ItemFormTest):
'form-1-min_count': '1',
'form-1-max_count': '2',
})
assert not self.item2.addons.exists()
with scopes_disabled():
assert not self.item2.addons.exists()
def test_manipulate_bundles(self):
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
@@ -409,8 +441,9 @@ class ItemsTest(ItemFormTest):
'form-0-count': '2',
'form-0-designated_price': '2.00',
})
assert self.item2.bundles.exists()
assert self.item2.bundles.first().bundled_item == self.item1
with scopes_disabled():
assert self.item2.bundles.exists()
assert self.item2.bundles.first().bundled_item == self.item1
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
@@ -422,7 +455,8 @@ class ItemsTest(ItemFormTest):
'form-0-designated_price': '2.00',
'form-0-DELETE': 'on',
})
assert not self.item2.bundles.exists()
with scopes_disabled():
assert not self.item2.bundles.exists()
# Do not allow self-reference
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
@@ -435,10 +469,12 @@ class ItemsTest(ItemFormTest):
'form-0-count': '2',
'form-0-designated_price': '2.00',
})
assert not self.item2.bundles.exists()
with scopes_disabled():
assert not self.item2.bundles.exists()
# Do not allow multi-level bundles
self.item1.bundles.create(bundled_item=self.item1, count=1, designated_price=0)
with scopes_disabled():
self.item1.bundles.create(bundled_item=self.item1, count=1, designated_price=0)
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
@@ -449,7 +485,8 @@ class ItemsTest(ItemFormTest):
'form-0-count': '2',
'form-0-designated_price': '2.00',
})
assert not self.item2.bundles.exists()
with scopes_disabled():
assert not self.item2.bundles.exists()
def test_update_variations(self):
self.client.post('/control/event/%s/%s/items/%d/variations' % (self.orga1.slug, self.event1.slug, self.item2.id), {
@@ -491,39 +528,45 @@ class ItemsTest(ItemFormTest):
'active': 'yes',
'allow_cancel': 'yes'
})
assert not self.item2.variations.filter(pk=self.var2.pk).exists()
with scopes_disabled():
assert not self.item2.variations.filter(pk=self.var2.pk).exists()
def test_delete(self):
self.client.post('/control/event/%s/%s/items/%d/delete' % (self.orga1.slug, self.event1.slug, self.item1.id),
{})
assert not self.event1.items.filter(pk=self.item1.pk).exists()
with scopes_disabled():
assert not self.event1.items.filter(pk=self.item1.pk).exists()
self.client.post('/control/event/%s/%s/items/%d/delete' % (self.orga1.slug, self.event1.slug, self.item2.id),
{})
assert not self.event1.items.filter(pk=self.item2.pk).exists()
with scopes_disabled():
assert not self.event1.items.filter(pk=self.item2.pk).exists()
def test_delete_ordered(self):
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.item1,
variation=None,
price=Decimal("14"),
attendee_name_parts={'full_name': "Peter"}
)
with scopes_disabled():
o = Order.objects.create(
code='FOO', event=self.event1, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + datetime.timedelta(days=10),
total=14, locale='en'
)
OrderPosition.objects.create(
order=o,
item=self.item1,
variation=None,
price=Decimal("14"),
attendee_name_parts={'full_name': "Peter"}
)
self.client.post('/control/event/%s/%s/items/%d/delete' % (self.orga1.slug, self.event1.slug, self.item1.id),
{})
assert self.event1.items.filter(pk=self.item1.pk).exists()
with scopes_disabled():
assert self.event1.items.filter(pk=self.item1.pk).exists()
self.item1.refresh_from_db()
assert not self.item1.active
def test_create_copy(self):
q = Question.objects.create(event=self.event1, question="Size", type="N")
q.items.add(self.item2)
with scopes_disabled():
q = Question.objects.create(event=self.event1, question="Size", type="N")
q.items.add(self.item2)
self.item2.sales_channels = ["web", "bar"]
self.client.post('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug), {
@@ -533,22 +576,24 @@ class ItemsTest(ItemFormTest):
'copy_from': str(self.item2.pk),
'has_variations': '1'
})
i_old = Item.objects.get(name__icontains='Business')
i_new = Item.objects.get(name__icontains='Intermediate')
assert i_new.category == i_old.category
assert i_new.description == i_old.description
assert i_new.active == i_old.active
assert i_new.available_from == i_old.available_from
assert i_new.available_until == i_old.available_until
assert i_new.require_voucher == i_old.require_voucher
assert i_new.hide_without_voucher == i_old.hide_without_voucher
assert i_new.allow_cancel == i_old.allow_cancel
assert i_new.sales_channels == i_old.sales_channels
assert set(i_new.questions.all()) == set(i_old.questions.all())
assert set([str(v.value) for v in i_new.variations.all()]) == set([str(v.value) for v in i_old.variations.all()])
with scopes_disabled():
i_old = Item.objects.get(name__icontains='Business')
i_new = Item.objects.get(name__icontains='Intermediate')
assert i_new.category == i_old.category
assert i_new.description == i_old.description
assert i_new.active == i_old.active
assert i_new.available_from == i_old.available_from
assert i_new.available_until == i_old.available_until
assert i_new.require_voucher == i_old.require_voucher
assert i_new.hide_without_voucher == i_old.hide_without_voucher
assert i_new.allow_cancel == i_old.allow_cancel
assert i_new.sales_channels == i_old.sales_channels
assert set(i_new.questions.all()) == set(i_old.questions.all())
assert set([str(v.value) for v in i_new.variations.all()]) == set([str(v.value) for v in i_old.variations.all()])
def test_add_to_existing_quota(self):
q = Quota.objects.create(event=self.event1, name="New Test Quota", size=50)
with scopes_disabled():
q = Quota.objects.create(event=self.event1, name="New Test Quota", size=50)
doc = self.get_doc('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug))
form_data = extract_form_fields(doc.select('.container-fluid form')[0])
@@ -558,10 +603,11 @@ class ItemsTest(ItemFormTest):
form_data['quota_add_existing'] = str(q.pk)
doc = self.post_doc('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug), form_data)
i = Item.objects.get(name__icontains='Existing')
with scopes_disabled():
i = Item.objects.get(name__icontains='Existing')
assert doc.select(".alert-success")
assert q.items.filter(pk=i.pk).exists()
assert doc.select(".alert-success")
assert q.items.filter(pk=i.pk).exists()
def test_add_to_new_quota(self):
doc = self.get_doc('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug))
@@ -574,8 +620,9 @@ class ItemsTest(ItemFormTest):
doc = self.post_doc('/control/event/%s/%s/items/add' % (self.orga1.slug, self.event1.slug), form_data)
assert doc.select(".alert-success")
assert Quota.objects.filter(name__icontains='New Quota').exists()
assert Item.objects.filter(name__icontains='New Item').exists()
i = Item.objects.get(name__icontains='New Item')
q = Quota.objects.get(name__icontains='New Quota')
assert q.items.filter(pk=i.pk).exists()
with scopes_disabled():
assert Quota.objects.filter(name__icontains='New Quota').exists()
assert Item.objects.filter(name__icontains='New Item').exists()
i = Item.objects.get(name__icontains='New Item')
q = Quota.objects.get(name__icontains='New Quota')
assert q.items.filter(pk=i.pk).exists()

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,13 @@
import datetime
from django_scopes import scopes_disabled
from tests.base import SoupTest, extract_form_fields
from pretix.base.models import Event, Organizer, Team, User
class OrganizerTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')

View File

@@ -2,6 +2,7 @@ import datetime
from decimal import Decimal
from django.utils.timezone import now
from django_scopes import scopes_disabled
from tests.base import SoupTest
from pretix.base.models import (
@@ -10,6 +11,7 @@ from pretix.base.models import (
class OrderSearchTest(SoupTest):
@scopes_disabled()
def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
@@ -67,21 +69,21 @@ class OrderSearchTest(SoupTest):
self.client.login(email='dummy@dummy.dummy', password='dummy')
def test_team_limit_event(self):
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' in resp
assert 'FO2' not in resp
def test_team_limit_event_wrong_permission(self):
self.team.can_view_orders = False
self.team.save()
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' not in resp
assert 'FO2' not in resp
def test_team_all_events(self):
self.team.all_events = True
self.team.save()
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' in resp
assert 'FO2' in resp
@@ -89,13 +91,13 @@ class OrderSearchTest(SoupTest):
self.team.all_events = True
self.team.can_view_orders = False
self.team.save()
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' not in resp
assert 'FO2' not in resp
def test_team_none(self):
self.team.members.clear()
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' not in resp
assert 'FO2' not in resp
@@ -104,44 +106,44 @@ class OrderSearchTest(SoupTest):
self.user.staffsession_set.create(date_start=now(), session_key=self.client.session.session_key)
self.user.save()
self.team.members.clear()
resp = self.client.get('/control/search/orders/').rendered_content
resp = self.client.get('/control/search/orders/').content.decode()
assert 'FO1' in resp
assert 'FO2' in resp
def test_filter_email(self):
resp = self.client.get('/control/search/orders/?query=dummy1@dummy').rendered_content
resp = self.client.get('/control/search/orders/?query=dummy1@dummy').content.decode()
assert 'FO1' in resp
resp = self.client.get('/control/search/orders/?query=dummynope').rendered_content
resp = self.client.get('/control/search/orders/?query=dummynope').content.decode()
assert 'FO1' not in resp
def test_filter_attendee_name(self):
resp = self.client.get('/control/search/orders/?query=Pete').rendered_content
resp = self.client.get('/control/search/orders/?query=Pete').content.decode()
assert 'FO1' in resp
resp = self.client.get('/control/search/orders/?query=Mark').rendered_content
resp = self.client.get('/control/search/orders/?query=Mark').content.decode()
assert 'FO1' not in resp
def test_filter_attendee_email(self):
resp = self.client.get('/control/search/orders/?query=att.com').rendered_content
resp = self.client.get('/control/search/orders/?query=att.com').content.decode()
assert 'FO1' in resp
resp = self.client.get('/control/search/orders/?query=nope.com').rendered_content
resp = self.client.get('/control/search/orders/?query=nope.com').content.decode()
assert 'FO1' not in resp
def test_filter_invoice_address(self):
resp = self.client.get('/control/search/orders/?query=Ltd').rendered_content
resp = self.client.get('/control/search/orders/?query=Ltd').content.decode()
assert 'FO1' in resp
resp = self.client.get('/control/search/orders/?query=Miller').rendered_content
resp = self.client.get('/control/search/orders/?query=Miller').content.decode()
assert 'FO1' in resp
def test_filter_code(self):
resp = self.client.get('/control/search/orders/?query=FO1').rendered_content
resp = self.client.get('/control/search/orders/?query=FO1').content.decode()
assert '30C3-FO1' in resp
resp = self.client.get('/control/search/orders/?query=30c3-FO1').rendered_content
resp = self.client.get('/control/search/orders/?query=30c3-FO1').content.decode()
assert '30C3-FO1' in resp
resp = self.client.get('/control/search/orders/?query=30C3-fO1A').rendered_content
resp = self.client.get('/control/search/orders/?query=30C3-fO1A').content.decode()
assert '30C3-FO1' in resp
resp = self.client.get('/control/search/orders/?query=30C3-fo14').rendered_content
resp = self.client.get('/control/search/orders/?query=30C3-fo14').content.decode()
assert '30C3-FO1' in resp
resp = self.client.get('/control/search/orders/?query=31c3-FO1').rendered_content
resp = self.client.get('/control/search/orders/?query=31c3-FO1').content.decode()
assert '30C3-FO1' not in resp
resp = self.client.get('/control/search/orders/?query=FO2').rendered_content
resp = self.client.get('/control/search/orders/?query=FO2').content.decode()
assert '30C3-FO1' not in resp

Some files were not shown because too many files have changed in this diff Show More