forked from CGM_Public/pretix_original
Web check-in: Show addons of ticket (Z#23220213) (#5827)
* Web check-in: Show addons of ticket (Z#23220213) * Update src/pretix/plugins/webcheckin/static/pretixplugins/webcheckin/components/app.vue Co-authored-by: luelista <weller@rami.io> --------- Co-authored-by: luelista <weller@rami.io>
This commit is contained in:
@@ -704,6 +704,16 @@ class CheckinListOrderPositionSerializer(OrderPositionSerializer):
|
|||||||
if 'answers.question' in self.context['expand']:
|
if 'answers.question' in self.context['expand']:
|
||||||
self.fields['answers'].child.fields['question'] = QuestionSerializer(read_only=True)
|
self.fields['answers'].child.fields['question'] = QuestionSerializer(read_only=True)
|
||||||
|
|
||||||
|
if 'addons' in self.context['expand']:
|
||||||
|
# Experimental feature, undocumented on purpose for now in case we need to remove it again
|
||||||
|
# for performance reasons
|
||||||
|
subl = CheckinListOrderPositionSerializer(read_only=True, many=True, context={
|
||||||
|
**self.context,
|
||||||
|
'expand': [v for v in self.context['expand'] if v != 'addons'],
|
||||||
|
'pdf_data': False,
|
||||||
|
})
|
||||||
|
self.fields['addons'] = subl
|
||||||
|
|
||||||
|
|
||||||
class OrderPaymentTypeField(serializers.Field):
|
class OrderPaymentTypeField(serializers.Field):
|
||||||
# TODO: Remove after pretix 2.2
|
# TODO: Remove after pretix 2.2
|
||||||
|
|||||||
@@ -381,15 +381,21 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
|||||||
|
|
||||||
qs = qs.filter(reduce(operator.or_, lists_qs))
|
qs = qs.filter(reduce(operator.or_, lists_qs))
|
||||||
|
|
||||||
|
prefetch_related = [
|
||||||
|
Prefetch(
|
||||||
|
lookup='checkins',
|
||||||
|
queryset=Checkin.objects.filter(list_id__in=[cl.pk for cl in checkinlists]).select_related('device')
|
||||||
|
),
|
||||||
|
Prefetch('print_logs', queryset=PrintLog.objects.select_related('device')),
|
||||||
|
'answers', 'answers__options', 'answers__question',
|
||||||
|
]
|
||||||
|
select_related = [
|
||||||
|
'item', 'variation', 'order', 'addon_to', 'order__invoice_address', 'order', 'seat'
|
||||||
|
]
|
||||||
|
|
||||||
if pdf_data:
|
if pdf_data:
|
||||||
qs = qs.prefetch_related(
|
qs = qs.prefetch_related(
|
||||||
Prefetch(
|
# Don't add to list, we don't want to propagate to addons
|
||||||
lookup='checkins',
|
|
||||||
queryset=Checkin.objects.filter(list_id__in=[cl.pk for cl in checkinlists]).select_related('device')
|
|
||||||
),
|
|
||||||
Prefetch('print_logs', queryset=PrintLog.objects.select_related('device')),
|
|
||||||
'answers', 'answers__options', 'answers__question',
|
|
||||||
Prefetch('addons', OrderPosition.objects.select_related('item', 'variation')),
|
|
||||||
Prefetch('order', Order.objects.select_related('invoice_address').prefetch_related(
|
Prefetch('order', Order.objects.select_related('invoice_address').prefetch_related(
|
||||||
Prefetch(
|
Prefetch(
|
||||||
'event',
|
'event',
|
||||||
@@ -404,32 +410,39 @@ def _checkin_list_position_queryset(checkinlists, ignore_status=False, ignore_pr
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
).select_related(
|
|
||||||
'item', 'variation', 'item__category', 'addon_to', 'order', 'order__invoice_address', 'seat'
|
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
qs = qs.prefetch_related(
|
|
||||||
Prefetch(
|
|
||||||
lookup='checkins',
|
|
||||||
queryset=Checkin.objects.filter(list_id__in=[cl.pk for cl in checkinlists]).select_related('device')
|
|
||||||
),
|
|
||||||
Prefetch('print_logs', queryset=PrintLog.objects.select_related('device')),
|
|
||||||
'answers', 'answers__options', 'answers__question',
|
|
||||||
Prefetch('addons', OrderPosition.objects.select_related('item', 'variation'))
|
|
||||||
).select_related('item', 'variation', 'order', 'addon_to', 'order__invoice_address', 'order', 'seat')
|
|
||||||
|
|
||||||
if expand and 'subevent' in expand:
|
if expand and 'subevent' in expand:
|
||||||
qs = qs.prefetch_related(
|
prefetch_related += [
|
||||||
'subevent', 'subevent__event', 'subevent__subeventitem_set', 'subevent__subeventitemvariation_set',
|
'subevent', 'subevent__event', 'subevent__subeventitem_set', 'subevent__subeventitemvariation_set',
|
||||||
'subevent__seat_category_mappings', 'subevent__meta_values'
|
'subevent__seat_category_mappings', 'subevent__meta_values'
|
||||||
)
|
]
|
||||||
|
|
||||||
if expand and 'item' in expand:
|
if expand and 'item' in expand:
|
||||||
qs = qs.prefetch_related('item', 'item__addons', 'item__bundles', 'item__meta_values',
|
prefetch_related += [
|
||||||
'item__variations').select_related('item__tax_rule')
|
'item', 'item__addons', 'item__bundles', 'item__meta_values',
|
||||||
|
'item__variations',
|
||||||
|
]
|
||||||
|
select_related.append('item__tax_rule')
|
||||||
|
|
||||||
if expand and 'variation' in expand:
|
if expand and 'variation' in expand:
|
||||||
qs = qs.prefetch_related('variation', 'variation__meta_values')
|
prefetch_related += [
|
||||||
|
'variation', 'variation__meta_values',
|
||||||
|
]
|
||||||
|
|
||||||
|
if expand and 'addons' in expand:
|
||||||
|
prefetch_related += [
|
||||||
|
Prefetch('addons', OrderPosition.objects.prefetch_related(*prefetch_related).select_related(*select_related)),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
prefetch_related += [
|
||||||
|
Prefetch('addons', OrderPosition.objects.select_related('item', 'variation'))
|
||||||
|
]
|
||||||
|
|
||||||
|
if pdf_data:
|
||||||
|
select_related.remove("order") # Don't need it twice on this queryset
|
||||||
|
|
||||||
|
qs = qs.prefetch_related(*prefetch_related).select_related(*select_related)
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<div class="details">
|
<div class="details">
|
||||||
<code>{{ checkResult.position.order }}-{{ checkResult.position.positionid }}</code>
|
<code>{{ checkResult.position.order }}-{{ checkResult.position.positionid }}</code>
|
||||||
<h4>{{ checkResult.position.attendee_name }}</h4>
|
<h4>{{ checkResult.position.attendee_name }}</h4>
|
||||||
|
<div v-if="checkResultAddons" class="addons">{{ checkResultAddons }}</div>
|
||||||
<span v-if="checkResultSubevent">{{ checkResultSubevent }}<br></span>
|
<span v-if="checkResultSubevent">{{ checkResultSubevent }}<br></span>
|
||||||
<span class="secret">{{ checkResult.position.secret }}</span>
|
<span class="secret">{{ checkResult.position.secret }}</span>
|
||||||
<span v-if="checkResult.position.seat"><br>{{ checkResult.position.seat.name }}</span>
|
<span v-if="checkResult.position.seat"><br>{{ checkResult.position.seat.name }}</span>
|
||||||
@@ -265,6 +266,16 @@ export default {
|
|||||||
const date = moment.utc(this.checkinlist.subevent.date_from).tz(this.$root.timezone).format(this.$root.datetime_format)
|
const date = moment.utc(this.checkinlist.subevent.date_from).tz(this.$root.timezone).format(this.$root.datetime_format)
|
||||||
return `${name} · ${date}`
|
return `${name} · ${date}`
|
||||||
},
|
},
|
||||||
|
checkResultAddons() {
|
||||||
|
if (!this.checkResult) return ''
|
||||||
|
if (!this.checkResult.position.addons) return ''
|
||||||
|
return this.checkResult.position.addons.map((addon) => {
|
||||||
|
if (addon.variation) {
|
||||||
|
return `+ ${addon.item.internal_name || i18nstring_localize(addon.item.name)} – ${i18nstring_localize(addon.variation.value)}`
|
||||||
|
}
|
||||||
|
return "+ " + (addon.item.internal_name || i18nstring_localize(addon.item.name));
|
||||||
|
}).join("\n")
|
||||||
|
},
|
||||||
checkResultSubevent() {
|
checkResultSubevent() {
|
||||||
if (!this.checkResult) return ''
|
if (!this.checkResult) return ''
|
||||||
if (!this.checkResult.position.subevent) return ''
|
if (!this.checkResult.position.subevent) return ''
|
||||||
@@ -369,7 +380,7 @@ export default {
|
|||||||
this.$refs.input.blur()
|
this.$refs.input.blur()
|
||||||
})
|
})
|
||||||
|
|
||||||
let url = this.$root.api.lists + this.checkinlist.id + '/positions/' + encodeURIComponent(id) + '/redeem/?expand=item&expand=subevent&expand=variation&expand=answers.question'
|
let url = this.$root.api.lists + this.checkinlist.id + '/positions/' + encodeURIComponent(id) + '/redeem/?expand=item&expand=subevent&expand=variation&expand=answers.question&expand=addons'
|
||||||
if (untrusted) {
|
if (untrusted) {
|
||||||
url += '&untrusted_input=true'
|
url += '&untrusted_input=true'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ a.searchresult, .check-result {
|
|||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
color: $text-muted;
|
color: $text-muted;
|
||||||
}
|
}
|
||||||
|
.addons {
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.check-result-status {
|
.check-result-status {
|
||||||
|
|||||||
@@ -737,6 +737,19 @@ def test_question_expand(token_client, organizer, clist, event, order, question)
|
|||||||
assert resp.data["position"]["answers"][0]["question"]["question"]["en"] == "Size"
|
assert resp.data["position"]["answers"][0]["question"]["question"]["en"] == "Size"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_addons_expand(token_client, organizer, clist, event, order, question, other_item):
|
||||||
|
with scopes_disabled():
|
||||||
|
p = order.positions.first()
|
||||||
|
question[0].save()
|
||||||
|
p.answers.create(question=question[0], answer="3")
|
||||||
|
|
||||||
|
resp = _redeem(token_client, organizer, clist, p.secret, {"answers": {question[0].pk: ""}}, query="?expand=addons&expand=item")
|
||||||
|
assert resp.status_code == 201
|
||||||
|
assert resp.data["status"] == "ok"
|
||||||
|
assert resp.data["position"]["addons"][0]["item"]["id"] == other_item.pk
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_store_failed(token_client, organizer, clist, event, order):
|
def test_store_failed(token_client, organizer, clist, event, order):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
|
|||||||
Reference in New Issue
Block a user