mirror of
https://github.com/pretix/pretix.git
synced 2026-09-14 16:24:43 +00:00
add edit view for waitinglist entry
This commit is contained in:
@@ -19,12 +19,18 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||||
# <https://www.gnu.org/licenses/>.
|
# <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
from django.forms import ChoiceField, EmailField
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.html import escape
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django_scopes.forms import SafeModelChoiceField
|
from django_scopes.forms import SafeModelChoiceField
|
||||||
|
from phonenumber_field.formfields import PhoneNumberField
|
||||||
|
|
||||||
from pretix.base.forms import I18nModelForm
|
from pretix.base.forms import I18nModelForm
|
||||||
from pretix.base.models import WaitingListEntry
|
from pretix.base.forms.questions import NamePartsFormField
|
||||||
from pretix.control.forms.widgets import Select2
|
from pretix.base.models import Item, ItemVariation, WaitingListEntry
|
||||||
|
from pretix.control.forms.widgets import Select2, Select2ItemVarQuota
|
||||||
|
|
||||||
|
|
||||||
class WaitingListEntryTransferForm(I18nModelForm):
|
class WaitingListEntryTransferForm(I18nModelForm):
|
||||||
@@ -54,3 +60,93 @@ class WaitingListEntryTransferForm(I18nModelForm):
|
|||||||
field_classes = {
|
field_classes = {
|
||||||
'subevent': SafeModelChoiceField,
|
'subevent': SafeModelChoiceField,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WaitingListEntryEditForm(I18nModelForm):
|
||||||
|
itemvar = ChoiceField()
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.instance = kwargs.get('instance', None)
|
||||||
|
initial = kwargs.get('initial', {})
|
||||||
|
if self.instance and self.instance.pk and 'itemvar' not in initial:
|
||||||
|
if self.instance.variation is not None:
|
||||||
|
initial['itemvar'] = f'{self.instance.item.pk}-{self.instance.variation.pk}'
|
||||||
|
else:
|
||||||
|
initial['itemvar'] = self.instance.item.pk
|
||||||
|
kwargs['initial'] = initial
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Prevent the item field cleaning from complaining that it isn't populated
|
||||||
|
# the value for item is derived and populated during form.clean()
|
||||||
|
self.fields['item'].required = False
|
||||||
|
|
||||||
|
self.fields['name_parts'] = NamePartsFormField(
|
||||||
|
max_length=255,
|
||||||
|
required=True,
|
||||||
|
scheme=self.event.organizer.settings.name_scheme,
|
||||||
|
titles=self.event.organizer.settings.name_scheme_titles,
|
||||||
|
label=_('Name'),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fields['name_parts'].required = self.event.settings.waiting_list_names_required
|
||||||
|
self.fields['phone'].required = self.event.settings.waiting_list_phones_required
|
||||||
|
|
||||||
|
choices = []
|
||||||
|
|
||||||
|
items = self.event.items.prefetch_related('variations')
|
||||||
|
for item in items:
|
||||||
|
if len(item.variations.all()) > 0:
|
||||||
|
for v in item.variations.all():
|
||||||
|
choices.append((
|
||||||
|
'{}-{}'.format(item.pk, v.pk),
|
||||||
|
'{} – {}'.format(item, v.value) if item.active else mark_safe(
|
||||||
|
f'<strike class="text-muted">{escape(item)} – {escape(v.value)}</strike>')
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
choices.append(('{}'.format(item.pk), str(item) if item.active else mark_safe(
|
||||||
|
f'<strike class="text-muted">{escape(item)}</strike>')))
|
||||||
|
|
||||||
|
self.fields['itemvar'].label = _("Item and Variation")
|
||||||
|
self.fields['itemvar'].required = True
|
||||||
|
self.fields['itemvar'].widget = Select2ItemVarQuota(
|
||||||
|
attrs={
|
||||||
|
'data-model-select2': 'generic',
|
||||||
|
'data-select2-url': reverse('control:event.items.itemvars.select2', kwargs={
|
||||||
|
'event': self.event.slug,
|
||||||
|
'organizer': self.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
choices=choices
|
||||||
|
)
|
||||||
|
self.fields['itemvar'].choices = choices
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super().clean()
|
||||||
|
itemvar = cleaned_data.get('itemvar')
|
||||||
|
|
||||||
|
cleaned_data['item'] = Item.objects.get(pk=itemvar.split('-')[0])
|
||||||
|
if '-' in itemvar:
|
||||||
|
cleaned_data['variation'] = ItemVariation.objects.get(pk=itemvar.split('-')[1])
|
||||||
|
return cleaned_data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = WaitingListEntry
|
||||||
|
fields = [
|
||||||
|
'email',
|
||||||
|
'name_parts',
|
||||||
|
'phone',
|
||||||
|
'item',
|
||||||
|
'variation',
|
||||||
|
]
|
||||||
|
field_classes = {
|
||||||
|
'email': EmailField,
|
||||||
|
'phone': PhoneNumberField,
|
||||||
|
'item': SafeModelChoiceField,
|
||||||
|
'variation': SafeModelChoiceField,
|
||||||
|
}
|
||||||
|
exclude = [
|
||||||
|
'subevent', # handled by EntryTransfer view
|
||||||
|
'voucher', # handled by the assign operation in the WaitingListActionView
|
||||||
|
'priority' # handled via thumbs up/down
|
||||||
|
]
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends "pretixcontrol/event/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% block title %}{% trans "Edit waiting list entry" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Edit waiting list entry" %}</h1>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% bootstrap_field form.email layout="control" %}
|
||||||
|
{% if names_asked %}
|
||||||
|
{% bootstrap_field form.name_parts layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
{% if phones_asked %}
|
||||||
|
{% bootstrap_field form.phone layout="control" %}
|
||||||
|
{% endif %}
|
||||||
|
{% bootstrap_field form.itemvar layout="control" %}
|
||||||
|
<div class="form-group submit-group">
|
||||||
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
|
{% trans "Submit" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -274,6 +274,7 @@
|
|||||||
<i class="fa fa-calendar" aria-hidden="true"></i>
|
<i class="fa fa-calendar" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a href="{% url "control:event.orders.waitinglist.edit" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}" class="btn btn-default btn-sm"><i class="fa fa-pencil"></i></a>
|
||||||
<a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="btn btn-default btn-sm disabled">
|
<button class="btn btn-default btn-sm disabled">
|
||||||
|
|||||||
@@ -474,6 +474,8 @@ urlpatterns = [
|
|||||||
re_path(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'),
|
re_path(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'),
|
||||||
re_path(r'^waitinglist/action$', waitinglist.WaitingListActionView.as_view(), name='event.orders.waitinglist.action'),
|
re_path(r'^waitinglist/action$', waitinglist.WaitingListActionView.as_view(), name='event.orders.waitinglist.action'),
|
||||||
re_path(r'^waitinglist/auto_assign$', waitinglist.AutoAssign.as_view(), name='event.orders.waitinglist.auto'),
|
re_path(r'^waitinglist/auto_assign$', waitinglist.AutoAssign.as_view(), name='event.orders.waitinglist.auto'),
|
||||||
|
re_path(r'^waitinglist/(?P<entry>\d+)/edit$', waitinglist.EntryEdit.as_view(),
|
||||||
|
name='event.orders.waitinglist.edit'),
|
||||||
re_path(r'^waitinglist/(?P<entry>\d+)/delete$', waitinglist.EntryDelete.as_view(),
|
re_path(r'^waitinglist/(?P<entry>\d+)/delete$', waitinglist.EntryDelete.as_view(),
|
||||||
name='event.orders.waitinglist.delete'),
|
name='event.orders.waitinglist.delete'),
|
||||||
re_path(r'^waitinglist/(?P<entry>\d+)/transfer$', waitinglist.EntryTransfer.as_view(),
|
re_path(r'^waitinglist/(?P<entry>\d+)/transfer$', waitinglist.EntryTransfer.as_view(),
|
||||||
|
|||||||
@@ -53,7 +53,9 @@ from pretix.base.models import Item, LogEntry, Quota, WaitingListEntry
|
|||||||
from pretix.base.models.waitinglist import WaitingListException
|
from pretix.base.models.waitinglist import WaitingListException
|
||||||
from pretix.base.services.waitinglist import assign_automatically
|
from pretix.base.services.waitinglist import assign_automatically
|
||||||
from pretix.base.views.tasks import AsyncAction
|
from pretix.base.views.tasks import AsyncAction
|
||||||
from pretix.control.forms.waitinglist import WaitingListEntryTransferForm
|
from pretix.control.forms.waitinglist import (
|
||||||
|
WaitingListEntryEditForm, WaitingListEntryTransferForm,
|
||||||
|
)
|
||||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||||
from pretix.control.views import PaginationMixin
|
from pretix.control.views import PaginationMixin
|
||||||
|
|
||||||
@@ -390,6 +392,44 @@ class EntryDelete(EventPermissionRequiredMixin, CompatDeleteView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class EntryEdit(EventPermissionRequiredMixin, UpdateView):
|
||||||
|
model = WaitingListEntry
|
||||||
|
template_name = 'pretixcontrol/waitinglist/edit.html'
|
||||||
|
permission = 'can_change_orders'
|
||||||
|
form_class = WaitingListEntryEditForm
|
||||||
|
context_object_name = 'entry'
|
||||||
|
|
||||||
|
def get_object(self, queryset=None):
|
||||||
|
return get_object_or_404(WaitingListEntry, pk=self.kwargs['entry'], event=self.request.event)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
ctx = super().get_context_data(**kwargs)
|
||||||
|
ctx['names_asked'] = self.request.event.settings.waiting_list_names_asked
|
||||||
|
ctx['phones_asked'] = self.request.event.settings.waiting_list_phones_asked
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def form_valid(self, form):
|
||||||
|
messages.success(self.request, _('The waitinglist entry has been updated.'))
|
||||||
|
if form.has_changed():
|
||||||
|
self.object.log_action(
|
||||||
|
'pretix.event.orders.waitinglist.changed', user=self.request.user, data={
|
||||||
|
k: form.cleaned_data.get(k) for k in form.changed_data
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return super().form_valid(form)
|
||||||
|
|
||||||
|
def form_invalid(self, form):
|
||||||
|
messages.error(self.request, _('We could not save your changes. See below for details.'))
|
||||||
|
return super().form_invalid(form)
|
||||||
|
|
||||||
|
def get_success_url(self) -> str:
|
||||||
|
return reverse('control:event.orders.waitinglist', kwargs={
|
||||||
|
'event': self.request.event.slug,
|
||||||
|
'organizer': self.request.event.organizer.slug
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class EntryTransfer(EventPermissionRequiredMixin, UpdateView):
|
class EntryTransfer(EventPermissionRequiredMixin, UpdateView):
|
||||||
model = WaitingListEntry
|
model = WaitingListEntry
|
||||||
template_name = 'pretixcontrol/waitinglist/transfer.html'
|
template_name = 'pretixcontrol/waitinglist/transfer.html'
|
||||||
|
|||||||
Reference in New Issue
Block a user