forked from CGM_Public/pretix_original
Allow attendees to modify their data (Z#23152886) (#4138)
* Allow attendees to modify their data * Allow attendees to change ticket information * Update src/pretix/control/templates/pretixcontrol/event/settings.html Co-authored-by: Mira <weller@rami.io> * Update src/pretix/presale/views/order.py Co-authored-by: Mira <weller@rami.io> * Update src/pretix/base/services/placeholders.py Co-authored-by: Mira <weller@rami.io> * Tests fix * Fix test --------- Co-authored-by: Mira <weller@rami.io>
This commit is contained in:
@@ -29,6 +29,11 @@
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
{% trans "Your items" %}
|
||||
{% if position.can_modify_answers %}
|
||||
<a href="{% eventurl event "presale:event.order.position.modify" secret=position.web_secret position=position.positionid order=order.code %}" aria-label="{% trans "Change ordered items" %}" class="h6">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>{% trans "Change details" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{% extends "pretixpresale/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load rich_text %}
|
||||
{% block title %}{% trans "Modify ticket" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h2>
|
||||
{% blocktrans trimmed %}
|
||||
Modify ticket
|
||||
{% endblocktrans %}
|
||||
</h2>
|
||||
<form class="form-horizontal" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="panel-group" id="questions_accordion">
|
||||
{% for pos, forms in formgroups %}
|
||||
<details class="panel panel-default" open>
|
||||
<summary class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<strong>{{ pos.item.name }}{% if pos.variation %}
|
||||
– {{ pos.variation }}
|
||||
{% endif %}</strong>
|
||||
</h4>
|
||||
</summary>
|
||||
<div id="cp{{ pos.id }}">
|
||||
<div class="panel-body questions-form">
|
||||
{% for form in forms %}
|
||||
{% if form.pos.item != pos.item %}
|
||||
{# Add-Ons #}
|
||||
<legend>+ {{ form.pos.item.name }}{% if form.pos.variation %}
|
||||
– {{ form.pos.variation.value }}
|
||||
{% endif %}</legend>
|
||||
{% endif %}
|
||||
{% bootstrap_form form layout="checkout" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row checkout-button-row">
|
||||
<div class="col-md-4">
|
||||
<a class="btn btn-block btn-default btn-lg"
|
||||
href="{{ view.get_position_url }}">
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-4 col-md-offset-4">
|
||||
<button class="btn btn-block btn-primary btn-lg" type="submit">
|
||||
{% trans "Save changes" %}
|
||||
</button>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -158,6 +158,9 @@ event_patterns = [
|
||||
re_path(r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/change$',
|
||||
pretix.presale.views.order.OrderPositionChange.as_view(),
|
||||
name='event.order.position.change'),
|
||||
re_path(r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/modify$',
|
||||
pretix.presale.views.order.OrderPositionModify.as_view(),
|
||||
name='event.order.position.modify'),
|
||||
|
||||
re_path(r'^ical/?$',
|
||||
pretix.presale.views.event.EventIcalDownload.as_view(),
|
||||
|
||||
@@ -858,6 +858,78 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
@method_decorator(xframe_options_exempt, 'dispatch')
|
||||
class OrderPositionModify(EventViewMixin, OrderPositionDetailMixin, OrderQuestionsViewMixin, TemplateView):
|
||||
form_class = QuestionsForm
|
||||
invoice_form_class = None
|
||||
template_name = "pretixpresale/event/position_modify.html"
|
||||
|
||||
@cached_property
|
||||
def invoice_form(self):
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def positions(self):
|
||||
return [p for p in super().positions if p.pk == self.position.pk or p.addon_to_id == self.position.pk]
|
||||
|
||||
def get_question_override_sets(self, order_position, index):
|
||||
override_sets = [
|
||||
resp for recv, resp in question_form_fields_overrides.send(
|
||||
self.request.event,
|
||||
position=order_position,
|
||||
request=self.request
|
||||
)
|
||||
]
|
||||
for override in override_sets:
|
||||
for k in override:
|
||||
# We don't want initial values to be modified, they should come from the order directly
|
||||
override[k].pop('initial', None)
|
||||
|
||||
if order_position.used_membership and not order_position.used_membership.membership_type.transferable:
|
||||
override_sets.append({
|
||||
'attendee_name_parts': {
|
||||
'disabled': True
|
||||
}
|
||||
})
|
||||
|
||||
return override_sets
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
failed = not self.save()
|
||||
if failed:
|
||||
messages.error(self.request,
|
||||
_("We had difficulties processing your input. Please review the errors below."))
|
||||
return self.get(request, *args, **kwargs)
|
||||
self.order.log_action('pretix.event.order.modified', {
|
||||
'by_ticket_holder': True,
|
||||
'data': [{
|
||||
k: (f.cleaned_data.get(k).name
|
||||
if isinstance(f.cleaned_data.get(k), File)
|
||||
else f.cleaned_data.get(k))
|
||||
for k in f.changed_data
|
||||
} for f in self.forms]
|
||||
})
|
||||
order_modified.send(sender=self.request.event, order=self.order)
|
||||
|
||||
invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk})
|
||||
CachedTicket.objects.filter(order_position__order=self.order).delete()
|
||||
CachedCombinedTicket.objects.filter(order=self.order).delete()
|
||||
return redirect(self.get_position_url())
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.kwargs = kwargs
|
||||
if not self.position:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if not self.position.can_modify_answers:
|
||||
messages.error(request, _('You cannot modify this order'))
|
||||
return redirect(self.get_position_url())
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
@method_decorator(xframe_options_exempt, 'dispatch')
|
||||
class OrderCancel(EventViewMixin, OrderDetailMixin, TemplateView):
|
||||
template_name = "pretixpresale/event/order_cancel.html"
|
||||
|
||||
Reference in New Issue
Block a user