mirror of
https://github.com/pretix/pretix.git
synced 2026-06-11 01:25:13 +00:00
CheckinRPC: Also perform media exchange
This commit is contained in:
committed by
Raphael Michel
parent
1f4189d539
commit
b2380f794e
@@ -26,7 +26,7 @@ from rest_framework.exceptions import ValidationError
|
||||
from pretix.api.serializers.event import SubEventSerializer
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
from pretix.base.media import MEDIA_TYPES
|
||||
from pretix.base.models import Checkin, CheckinList
|
||||
from pretix.base.models import Checkin, CheckinList, Item
|
||||
|
||||
|
||||
class CheckinListSerializer(I18nAwareModelSerializer):
|
||||
@@ -88,6 +88,13 @@ class CheckinRPCRedeemInputSerializer(serializers.Serializer):
|
||||
nonce = serializers.CharField(required=False, allow_null=True)
|
||||
datetime = serializers.DateTimeField(required=False, allow_null=True)
|
||||
answers = serializers.JSONField(required=False, allow_null=True)
|
||||
media_type = serializers.ChoiceField(required=False, choices=MEDIA_TYPES)
|
||||
media_identifier = serializers.CharField(required=False)
|
||||
media_policy = serializers.ChoiceField(required=False, choices=Item.MEDIA_POLICIES)
|
||||
media_action = serializers.ChoiceField(required=False, choices=[
|
||||
('append', 'append'),
|
||||
('replace', 'replace'),
|
||||
])
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -72,6 +72,7 @@ from pretix.base.services.checkin import (
|
||||
CheckInError, RequiredMediaExchangeError, RequiredQuestionsError, SQLLogic,
|
||||
perform_checkin,
|
||||
)
|
||||
from pretix.base.services.media import perform_media_exchange
|
||||
from pretix.base.signals import checkin_annulled
|
||||
from pretix.helpers import OF_SELF
|
||||
|
||||
@@ -455,7 +456,8 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
||||
|
||||
def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force, checkin_type, ignore_unpaid, nonce,
|
||||
untrusted_input, user, auth, expand, pdf_data, request, questions_supported, canceled_supported,
|
||||
source_type='barcode', legacy_url_support=False, simulate=False, gate=None, use_order_locale=False):
|
||||
source_type='barcode', legacy_url_support=False, simulate=False, gate=None, use_order_locale=False,
|
||||
media_type=None, media_identifier=None, media_policy=None, media_action=None):
|
||||
if not checkinlists:
|
||||
raise ValidationError('No check-in list passed.')
|
||||
|
||||
@@ -803,26 +805,59 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
locale = op.order.event.settings.locale
|
||||
with language(locale):
|
||||
try:
|
||||
perform_checkin(
|
||||
op=op,
|
||||
clist=list_by_event[op.order.event_id],
|
||||
given_answers=given_answers,
|
||||
force=force,
|
||||
ignore_unpaid=ignore_unpaid,
|
||||
nonce=nonce,
|
||||
datetime=datetime,
|
||||
questions_supported=questions_supported,
|
||||
canceled_supported=canceled_supported,
|
||||
user=user,
|
||||
auth=auth,
|
||||
type=checkin_type,
|
||||
raw_barcode=raw_barcode_for_checkin,
|
||||
raw_source_type=source_type,
|
||||
from_revoked_secret=from_revoked_secret,
|
||||
simulate=simulate,
|
||||
gate=gate,
|
||||
reusable_media=media,
|
||||
)
|
||||
if all(k is not None for k in [media_type, media_identifier, media_policy, media_action]) and not media:
|
||||
with transaction.atomic():
|
||||
media = perform_media_exchange(
|
||||
organizer=request.organizer,
|
||||
media_type=media_type,
|
||||
media_identifier=media_identifier,
|
||||
media_policy=media_policy,
|
||||
media_action=media_action,
|
||||
op=op,
|
||||
)
|
||||
source_type = media.media_type.identifier
|
||||
|
||||
perform_checkin(
|
||||
op=op,
|
||||
clist=list_by_event[op.order.event_id],
|
||||
given_answers=given_answers,
|
||||
force=force,
|
||||
ignore_unpaid=ignore_unpaid,
|
||||
nonce=nonce,
|
||||
datetime=datetime,
|
||||
questions_supported=questions_supported,
|
||||
canceled_supported=canceled_supported,
|
||||
user=user,
|
||||
auth=auth,
|
||||
type=checkin_type,
|
||||
raw_barcode=raw_barcode_for_checkin,
|
||||
raw_source_type=source_type,
|
||||
from_revoked_secret=from_revoked_secret,
|
||||
simulate=simulate,
|
||||
gate=gate,
|
||||
reusable_media=media,
|
||||
)
|
||||
else:
|
||||
perform_checkin(
|
||||
op=op,
|
||||
clist=list_by_event[op.order.event_id],
|
||||
given_answers=given_answers,
|
||||
force=force,
|
||||
ignore_unpaid=ignore_unpaid,
|
||||
nonce=nonce,
|
||||
datetime=datetime,
|
||||
questions_supported=questions_supported,
|
||||
canceled_supported=canceled_supported,
|
||||
user=user,
|
||||
auth=auth,
|
||||
type=checkin_type,
|
||||
raw_barcode=raw_barcode_for_checkin,
|
||||
raw_source_type=source_type,
|
||||
from_revoked_secret=from_revoked_secret,
|
||||
simulate=simulate,
|
||||
gate=gate,
|
||||
reusable_media=media,
|
||||
)
|
||||
except RequiredQuestionsError as e:
|
||||
return Response({
|
||||
'status': 'incomplete',
|
||||
@@ -843,6 +878,17 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
'media_policy': e.media_policy,
|
||||
'media_type': e.media_type,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
'reason_explanation': e.msg,
|
||||
}, status=400)
|
||||
except ReusableMedium.DuplicateEntry:
|
||||
return Response({
|
||||
'status': 'error',
|
||||
'reason': Checkin.REASON_AMBIGUOUS,
|
||||
'reason_explanation': 'Reusable medium identifier is ambigous',
|
||||
'require_attention': op.require_checkin_attention,
|
||||
'checkin_texts': op.checkin_texts,
|
||||
'position': CheckinListOrderPositionSerializer(op, context=_make_context(context, op.order.event)).data,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
}, status=400)
|
||||
except CheckInError as e:
|
||||
if not simulate:
|
||||
@@ -1031,6 +1077,10 @@ class CheckinRPCRedeemView(views.APIView):
|
||||
canceled_supported=True,
|
||||
request=self.request, # this is not clean, but we need it in the serializers for URL generation
|
||||
legacy_url_support=False,
|
||||
media_type=s.validated_data.get('media_type'),
|
||||
media_identifier=s.validated_data.get('media_identifier'),
|
||||
media_policy=s.validated_data.get('media_policy'),
|
||||
media_action=s.validated_data.get('media_action'),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
||||
|
||||
return Response({"result": None})
|
||||
|
||||
@scopes_disabled() # we are sure enough that get_queryset() is correct, so we save some perforamnce
|
||||
@scopes_disabled() # we are sure enough that get_queryset() is correct, so we save some performance
|
||||
def list(self, request, **kwargs):
|
||||
date = serializers.DateTimeField().to_representation(now())
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
|
||||
@@ -138,6 +138,9 @@ class ReusableMedium(LoggedModel):
|
||||
]
|
||||
ordering = "identifier", "type", "organizer"
|
||||
|
||||
class DuplicateEntry(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MediumKeySet(models.Model):
|
||||
organizer = models.ForeignKey('Organizer', on_delete=models.CASCADE, related_name='medium_key_sets')
|
||||
|
||||
@@ -25,8 +25,8 @@ from django.db import IntegrityError
|
||||
from django.db.models import Q
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.models import GiftCardAcceptance
|
||||
from pretix.base.models.media import MediumKeySet
|
||||
from pretix.base.models import GiftCardAcceptance, Item
|
||||
from pretix.base.models.media import MediumKeySet, ReusableMedium
|
||||
|
||||
|
||||
def create_nfc_mf0aes_keyset(organizer):
|
||||
@@ -70,3 +70,36 @@ def get_keysets_for_organizer(organizer):
|
||||
if new_set:
|
||||
sets.append(new_set)
|
||||
return sets
|
||||
|
||||
|
||||
def perform_media_exchange(organizer, media_type, media_identifier, media_policy, media_action, op):
|
||||
medium = None
|
||||
|
||||
if media_policy in [Item.MEDIA_POLICY_REUSE, Item.MEDIA_POLICY_REUSE_OR_NEW]:
|
||||
try:
|
||||
medium = ReusableMedium.objects.get(
|
||||
type=media_type,
|
||||
identifier=media_identifier,
|
||||
organizer=organizer,
|
||||
)
|
||||
except ReusableMedium.DoesNotExist:
|
||||
pass
|
||||
|
||||
if not medium and media_policy in [Item.MEDIA_POLICY_NEW, Item.MEDIA_POLICY_REUSE_OR_NEW]:
|
||||
try:
|
||||
medium = ReusableMedium.objects.create(
|
||||
type=media_type,
|
||||
identifier=media_identifier,
|
||||
organizer=organizer,
|
||||
)
|
||||
except IntegrityError:
|
||||
raise ReusableMedium.DuplicateEntry()
|
||||
|
||||
if medium:
|
||||
if media_action == 'append':
|
||||
medium.linked_orderpositions.add(*[op])
|
||||
elif media_action == 'replace':
|
||||
medium.linked_orderpositions.set([op])
|
||||
medium.save()
|
||||
|
||||
return medium
|
||||
|
||||
Reference in New Issue
Block a user