Check-in API: require_attention and ignore_status

This commit is contained in:
Raphael Michel
2019-04-23 17:06:24 +02:00
parent 840b30c3c2
commit e7384f7e85
5 changed files with 56 additions and 11 deletions
+13 -2
View File
@@ -41,6 +41,11 @@ include_pending boolean If ``true``, th
The ``include_pending`` field has been added.
.. versionchanged:: 2.7
The ``positions`` subresource now contains the new attributes ``require_attention`` and ``order__status`` and
accepts the new ``ignore_status`` filter.
Endpoints
---------
@@ -339,8 +344,12 @@ Order position endpoints
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/
Returns a list of all order positions within a given event. The result is the same as
the :ref:`order-position-resource`, with one important difference: the ``checkins`` value will only include
check-ins for the selected list.
the :ref:`order-position-resource`, with the following differences:
* The ``checkins`` value will only include check-ins for the selected list.
* An additional boolean property ``require_attention`` will inform you whether either the order or the item
have the ``checkin_attention`` flag set.
**Example request**:
@@ -407,6 +416,8 @@ Order position endpoints
}
:query integer page: The page number in case of a multi-page result set, default is 1
:query string ignore_status: If set to ``true``, results will be returned regardles of the state of
the order they belong to and you will need to do your own filtering by order status.
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``order__code``,
``order__datetime``, ``positionid``, ``attendee_name``, ``last_checked_in`` and ``order__email``. Default:
``attendee_name,positionid``
+17
View File
@@ -179,6 +179,23 @@ class OrderPositionSerializer(I18nAwareModelSerializer):
self.fields.pop('pdf_data')
class RequireAttentionField(serializers.Field):
def to_representation(self, instance: OrderPosition):
return instance.order.checkin_attention or instance.item.checkin_attention
class CheckinListOrderPositionSerializer(OrderPositionSerializer):
require_attention = RequireAttentionField(source='*')
order__status = serializers.SlugRelatedField(read_only=True, slug_field='status', source='order')
class Meta:
model = OrderPosition
fields = ('id', 'order', 'positionid', 'item', 'variation', 'price', 'attendee_name', 'attendee_name_parts',
'attendee_email', 'voucher', 'tax_rate', 'tax_value', 'secret', 'addon_to', 'subevent', 'checkins',
'downloads', 'answers', 'tax_rule', 'pseudonymization_id', 'pdf_data', 'require_attention',
'order__status')
class OrderPaymentTypeField(serializers.Field):
# TODO: Remove after pretix 2.2
def to_representation(self, instance: Order):
+12 -8
View File
@@ -13,7 +13,7 @@ from rest_framework.response import Response
from pretix.api.serializers.checkin import CheckinListSerializer
from pretix.api.serializers.item import QuestionSerializer
from pretix.api.serializers.order import OrderPositionSerializer
from pretix.api.serializers.order import CheckinListOrderPositionSerializer
from pretix.api.views import RichOrderingFilter
from pretix.api.views.order import OrderPositionFilter
from pretix.base.models import (
@@ -153,7 +153,7 @@ class CheckinOrderPositionFilter(OrderPositionFilter):
class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = OrderPositionSerializer
serializer_class = CheckinListOrderPositionSerializer
queryset = OrderPosition.objects.none()
filter_backends = (DjangoFilterBackend, RichOrderingFilter)
ordering = ('attendee_name_cached', 'positionid')
@@ -199,11 +199,15 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
qs = OrderPosition.objects.filter(
order__event=self.request.event,
order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING] if self.checkinlist.include_pending else [Order.STATUS_PAID],
subevent=self.checkinlist.subevent
).annotate(
last_checked_in=Subquery(cqs)
)
if self.request.query_params.get('ignore_status', 'false') != 'true':
qs = qs.filter(
order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING] if self.checkinlist.include_pending else [Order.STATUS_PAID]
)
if self.request.query_params.get('pdf_data', 'false') == 'true':
qs = qs.prefetch_related(
Prefetch(
@@ -225,7 +229,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
)
))
).select_related(
'item', 'variation', 'item__category', 'addon_to'
'item', 'variation', 'item__category', 'addon_to', 'order'
)
else:
qs = qs.prefetch_related(
@@ -235,7 +239,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
),
'answers', 'answers__options', 'answers__question',
Prefetch('addons', OrderPosition.objects.select_related('item', 'variation'))
).select_related('item', 'variation', 'order', 'addon_to', 'order__invoice_address')
).select_related('item', 'variation', 'order', 'addon_to', 'order__invoice_address', 'order')
if not self.checkinlist.all_products:
qs = qs.filter(item__in=self.checkinlist.limit_products.values_list('id', flat=True))
@@ -281,7 +285,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
return Response({
'status': 'incomplete',
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
'position': OrderPositionSerializer(op, context=self.get_serializer_context()).data,
'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data,
'questions': [
QuestionSerializer(q).data for q in e.questions
]
@@ -291,13 +295,13 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
'status': 'error',
'reason': e.code,
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
'position': OrderPositionSerializer(op, context=self.get_serializer_context()).data
'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
}, status=400)
else:
return Response({
'status': 'ok',
'require_attention': op.item.checkin_attention or op.order.checkin_attention,
'position': OrderPositionSerializer(op, context=self.get_serializer_context()).data
'position': CheckinListOrderPositionSerializer(op, context=self.get_serializer_context()).data
}, status=201)
def get_object(self):
+2 -1
View File
@@ -100,6 +100,7 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
'list': self.list.pk,
'web': True
}, user=request.user)
op.order.touch()
messages.success(request, _('The selected check-ins have been reverted.'))
else:
@@ -247,7 +248,7 @@ class CheckinListDelete(EventPermissionRequiredMixin, DeleteView):
self.object = self.get_object()
success_url = self.get_success_url()
self.object.checkins.all().delete()
self.object.log_action(action='pretix.event.orders.deleted', user=request.user)
self.object.log_action(action='pretix.event.checkinlists.deleted', user=request.user)
self.object.delete()
messages.success(self.request, _('The selected list has been deleted.'))
return HttpResponseRedirect(success_url)
+12
View File
@@ -69,6 +69,8 @@ def order(event, item, other_item, taxrule):
TEST_ORDERPOSITION1_RES = {
"id": 1,
"require_attention": False,
"order__status": "p",
"order": "FOO",
"positionid": 1,
"item": 1,
@@ -92,6 +94,8 @@ TEST_ORDERPOSITION1_RES = {
TEST_ORDERPOSITION2_RES = {
"id": 2,
"require_attention": False,
"order__status": "p",
"order": "FOO",
"positionid": 2,
"item": 1,
@@ -372,6 +376,14 @@ def test_list_all_items_positions(token_client, organizer, event, clist, clist_a
assert resp.status_code == 200
assert [] == resp.data['results']
resp = token_client.get('/api/v1/organizers/{}/events/{}/checkinlists/{}/positions/?ignore_status=true'.format(
organizer.slug, event.slug, clist_all.pk
))
assert resp.status_code == 200
p1['order__status'] = 'n'
p2['order__status'] = 'n'
assert [p2, p1] == resp.data['results']
@pytest.mark.django_db
def test_list_limited_items_positions(token_client, organizer, event, clist, item, order):