forked from CGM_Public/pretix_original
New check-in features (#3022)
This commit is contained in:
@@ -273,7 +273,13 @@ with scopes_disabled():
|
||||
def check_rules_qs(self, queryset, name, value):
|
||||
if not self.checkinlist.rules:
|
||||
return queryset
|
||||
return queryset.filter(SQLLogic(self.checkinlist).apply(self.checkinlist.rules))
|
||||
return queryset.filter(
|
||||
SQLLogic(self.checkinlist).apply(self.checkinlist.rules)
|
||||
).filter(
|
||||
Q(valid_from__isnull=True) | Q(valid_from__lte=now()),
|
||||
Q(valid_until__isnull=True) | Q(valid_until__gte=now()),
|
||||
blocked__isnull=True,
|
||||
)
|
||||
|
||||
|
||||
def _handle_file_upload(data, user, auth):
|
||||
@@ -325,7 +331,13 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
||||
if checkinlist.subevent:
|
||||
list_q &= Q(subevent=checkinlist.subevent)
|
||||
if not ignore_status:
|
||||
list_q &= Q(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING] if checkinlist.include_pending else [Order.STATUS_PAID])
|
||||
if checkinlist.include_pending:
|
||||
list_q &= Q(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
|
||||
else:
|
||||
list_q &= Q(
|
||||
Q(order__status=Order.STATUS_PAID) |
|
||||
Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True)
|
||||
)
|
||||
if not checkinlist.all_products and not ignore_products:
|
||||
list_q &= Q(item__in=checkinlist.limit_products.values_list('id', flat=True))
|
||||
lists_qs.append(list_q)
|
||||
@@ -582,7 +594,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_AMBIGUOUS,
|
||||
'reason_explanation': None,
|
||||
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
|
||||
'require_attention': op.require_checkin_attention,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, op.order.event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
}, status=400)
|
||||
@@ -627,7 +639,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
except RequiredQuestionsError as e:
|
||||
return Response({
|
||||
'status': 'incomplete',
|
||||
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
|
||||
'require_attention': op.require_checkin_attention,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, op.order.event)).data,
|
||||
'questions': [
|
||||
QuestionSerializer(q).data for q in e.questions
|
||||
@@ -656,14 +668,14 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
'status': 'error',
|
||||
'reason': e.code,
|
||||
'reason_explanation': e.reason,
|
||||
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
|
||||
'require_attention': op.require_checkin_attention,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, op.order.event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
}, status=400)
|
||||
else:
|
||||
return Response({
|
||||
'status': 'ok',
|
||||
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
|
||||
'require_attention': op.require_checkin_attention,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, op.order.event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
}, status=201)
|
||||
|
||||
@@ -49,15 +49,15 @@ from rest_framework.response import Response
|
||||
|
||||
from pretix.api.models import OAuthAccessToken
|
||||
from pretix.api.serializers.order import (
|
||||
InvoiceSerializer, OrderCreateSerializer, OrderPaymentCreateSerializer,
|
||||
OrderPaymentSerializer, OrderPositionSerializer,
|
||||
OrderRefundCreateSerializer, OrderRefundSerializer, OrderSerializer,
|
||||
PriceCalcSerializer, RevokedTicketSecretSerializer,
|
||||
SimulatedOrderSerializer,
|
||||
BlockedTicketSecretSerializer, InvoiceSerializer, OrderCreateSerializer,
|
||||
OrderPaymentCreateSerializer, OrderPaymentSerializer,
|
||||
OrderPositionSerializer, OrderRefundCreateSerializer,
|
||||
OrderRefundSerializer, OrderSerializer, PriceCalcSerializer,
|
||||
RevokedTicketSecretSerializer, SimulatedOrderSerializer,
|
||||
)
|
||||
from pretix.api.serializers.orderchange import (
|
||||
OrderChangeOperationSerializer, OrderFeeChangeSerializer,
|
||||
OrderPositionChangeSerializer,
|
||||
BlockNameSerializer, OrderChangeOperationSerializer,
|
||||
OrderFeeChangeSerializer, OrderPositionChangeSerializer,
|
||||
OrderPositionCreateForExistingOrderSerializer,
|
||||
OrderPositionInfoPatchSerializer,
|
||||
)
|
||||
@@ -70,7 +70,9 @@ from pretix.base.models import (
|
||||
OrderRefund, Quota, SubEvent, SubEventMetaValue, TaxRule, TeamAPIToken,
|
||||
generate_secret,
|
||||
)
|
||||
from pretix.base.models.orders import QuestionAnswer, RevokedTicketSecret
|
||||
from pretix.base.models.orders import (
|
||||
BlockedTicketSecret, QuestionAnswer, RevokedTicketSecret,
|
||||
)
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.pdf import get_images
|
||||
from pretix.base.secrets import assign_ticket_secret
|
||||
@@ -287,7 +289,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
if order.status in (Order.STATUS_CANCELED, Order.STATUS_EXPIRED):
|
||||
raise PermissionDenied("Downloads are not available for canceled or expired orders.")
|
||||
|
||||
if order.status == Order.STATUS_PENDING and not request.event.settings.ticket_download_pending:
|
||||
if order.status == Order.STATUS_PENDING and not (order.valid_if_pending or request.event.settings.ticket_download_pending):
|
||||
raise PermissionDenied("Downloads are not available for pending orders.")
|
||||
|
||||
ct = CachedCombinedTicket.objects.filter(
|
||||
@@ -763,6 +765,16 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
}
|
||||
)
|
||||
|
||||
if 'valid_if_pending' in self.request.data and serializer.instance.valid_if_pending != self.request.data.get('valid_if_pending'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.valid_if_pending',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'new_value': self.request.data.get('valid_if_pending')
|
||||
}
|
||||
)
|
||||
|
||||
if 'email' in self.request.data and serializer.instance.email != self.request.data.get('email'):
|
||||
serializer.instance.email_known_to_work = False
|
||||
serializer.instance.log_action(
|
||||
@@ -1183,7 +1195,7 @@ class OrderPositionViewSet(viewsets.ModelViewSet):
|
||||
if pos.order.status in (Order.STATUS_CANCELED, Order.STATUS_EXPIRED):
|
||||
raise PermissionDenied("Downloads are not available for canceled or expired orders.")
|
||||
|
||||
if pos.order.status == Order.STATUS_PENDING and not request.event.settings.ticket_download_pending:
|
||||
if pos.order.status == Order.STATUS_PENDING and not (pos.order.valid_if_pending or request.event.settings.ticket_download_pending):
|
||||
raise PermissionDenied("Downloads are not available for pending orders.")
|
||||
if not pos.generate_ticket:
|
||||
raise PermissionDenied("Downloads are not enabled for this product.")
|
||||
@@ -1225,6 +1237,54 @@ class OrderPositionViewSet(viewsets.ModelViewSet):
|
||||
raise ValidationError(str(e))
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@action(detail=True, methods=['POST'])
|
||||
def add_block(self, request, **kwargs):
|
||||
serializer = BlockNameSerializer(
|
||||
data=request.data,
|
||||
context=self.get_serializer_context(),
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
instance = self.get_object()
|
||||
try:
|
||||
ocm = OrderChangeManager(
|
||||
instance.order,
|
||||
user=self.request.user if self.request.user.is_authenticated else None,
|
||||
auth=self.request.auth,
|
||||
notify=False,
|
||||
reissue_invoice=False,
|
||||
)
|
||||
ocm.add_block(instance, serializer.validated_data['name'])
|
||||
ocm.commit()
|
||||
except OrderError as e:
|
||||
raise ValidationError(str(e))
|
||||
except Quota.QuotaExceededException as e:
|
||||
raise ValidationError(str(e))
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@action(detail=True, methods=['POST'])
|
||||
def remove_block(self, request, **kwargs):
|
||||
serializer = BlockNameSerializer(
|
||||
data=request.data,
|
||||
context=self.get_serializer_context(),
|
||||
)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
instance = self.get_object()
|
||||
try:
|
||||
ocm = OrderChangeManager(
|
||||
instance.order,
|
||||
user=self.request.user if self.request.user.is_authenticated else None,
|
||||
auth=self.request.auth,
|
||||
notify=False,
|
||||
reissue_invoice=False,
|
||||
)
|
||||
ocm.remove_block(instance, serializer.validated_data['name'])
|
||||
ocm.commit()
|
||||
except OrderError as e:
|
||||
raise ValidationError(str(e))
|
||||
except Quota.QuotaExceededException as e:
|
||||
raise ValidationError(str(e))
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
try:
|
||||
ocm = OrderChangeManager(
|
||||
@@ -1785,3 +1845,25 @@ class RevokedSecretViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
def get_queryset(self):
|
||||
return RevokedTicketSecret.objects.filter(event=self.request.event)
|
||||
|
||||
|
||||
with scopes_disabled():
|
||||
class BlockedSecretFilter(FilterSet):
|
||||
updated_since = django_filters.IsoDateTimeFilter(field_name='updated', lookup_expr='gte')
|
||||
|
||||
class Meta:
|
||||
model = BlockedTicketSecret
|
||||
fields = ['blocked']
|
||||
|
||||
|
||||
class BlockedSecretViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = BlockedTicketSecretSerializer
|
||||
queryset = BlockedTicketSecret.objects.none()
|
||||
filter_backends = (DjangoFilterBackend, OrderingFilter)
|
||||
ordering = ('-updated', '-pk')
|
||||
filterset_class = BlockedSecretFilter
|
||||
permission = 'can_view_orders'
|
||||
write_permission = 'can_change_orders'
|
||||
|
||||
def get_queryset(self):
|
||||
return BlockedTicketSecret.objects.filter(event=self.request.event)
|
||||
|
||||
Reference in New Issue
Block a user