mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
Questions: filter answers by dateFrame (Z#23216406) (#5706)
* replace manual form with QuestionFilterForm * move form to form/item.py * filter using a dateFrameField * rename QuestionFilterForm to QuestionAnswerFilterForm Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * pass existing `opqs` into `filter_qs` Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * clean up filters * fix view errors * add labels * display validation failures on field/label * fix linting issues * adjust datetime comparisons from lte to lt & gte to gt * Change filter-form layout similar to order-filter-form * improve label texts Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * use order constants Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * use Order Constants in Form where possible * Change phrasing from Subevent to Date Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * include product variations in products filter * repair time zone comparisons * fix linting * move filter form to form/filter.py * remove references to timezone.utc Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * remove manual class statements Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * removes unnecessary check Co-authored-by: Richard Schreiber <schreiber@pretix.eu> * fix datetime comparison * Add full stop to error message to match style * unify var-names and code-indent --------- Co-authored-by: Richard Schreiber <schreiber@pretix.eu> Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
committed by
GitHub
parent
510c4850a5
commit
2e89fc0a94
@@ -61,6 +61,10 @@ from pretix.base.models import (
|
||||
SubEvent, SubEventMetaValue, Team, TeamAPIToken, TeamInvite, Voucher,
|
||||
)
|
||||
from pretix.base.signals import register_payment_providers
|
||||
from pretix.base.timeframes import (
|
||||
DateFrameField,
|
||||
resolve_timeframe_to_datetime_start_inclusive_end_exclusive,
|
||||
)
|
||||
from pretix.control.forms import SplitDateTimeField
|
||||
from pretix.control.forms.widgets import Select2, Select2ItemVarQuota
|
||||
from pretix.control.signals import order_search_filter_q
|
||||
@@ -1219,6 +1223,129 @@ class OrderPaymentSearchFilterForm(forms.Form):
|
||||
return qs
|
||||
|
||||
|
||||
class QuestionAnswerFilterForm(forms.Form):
|
||||
STATUS_VARIANTS = [
|
||||
("", _("All orders")),
|
||||
(Order.STATUS_PAID, _("Paid")),
|
||||
(Order.STATUS_PAID + 'v', _("Paid or confirmed")),
|
||||
(Order.STATUS_PENDING, _("Pending")),
|
||||
(Order.STATUS_PENDING + Order.STATUS_PAID, _("Pending or paid")),
|
||||
("o", _("Pending (overdue)")),
|
||||
(Order.STATUS_EXPIRED, _("Expired")),
|
||||
(Order.STATUS_PENDING + Order.STATUS_EXPIRED, _("Pending or expired")),
|
||||
(Order.STATUS_CANCELED, _("Canceled"))
|
||||
]
|
||||
|
||||
status = forms.ChoiceField(
|
||||
choices=STATUS_VARIANTS,
|
||||
required=False,
|
||||
label=_("Order status"),
|
||||
)
|
||||
item = forms.ChoiceField(
|
||||
choices=[],
|
||||
required=False,
|
||||
label=_("Products"),
|
||||
)
|
||||
subevent = forms.ModelChoiceField(
|
||||
queryset=SubEvent.objects.none(),
|
||||
required=False,
|
||||
empty_label=pgettext_lazy('subevent', 'All dates'),
|
||||
label=pgettext_lazy("subevent", "Date"),
|
||||
)
|
||||
date_range = DateFrameField(
|
||||
required=False,
|
||||
include_future_frames=True,
|
||||
label=_('Event date'),
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.event = kwargs.pop('event')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.initial['status'] = Order.STATUS_PENDING + Order.STATUS_PAID
|
||||
|
||||
choices = [('', _('All products'))]
|
||||
for i in self.event.items.prefetch_related('variations').all():
|
||||
variations = list(i.variations.all())
|
||||
if variations:
|
||||
choices.append((str(i.pk), _('{product} – Any variation').format(product=str(i))))
|
||||
for v in variations:
|
||||
choices.append(('%d-%d' % (i.pk, v.pk), '%s – %s' % (str(i), v.value)))
|
||||
else:
|
||||
choices.append((str(i.pk), str(i)))
|
||||
self.fields['item'].choices = choices
|
||||
|
||||
if self.event.has_subevents:
|
||||
self.fields["subevent"].queryset = self.event.subevents.all()
|
||||
self.fields['subevent'].widget = Select2(
|
||||
attrs={
|
||||
'data-model-select2': 'event',
|
||||
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
|
||||
'event': self.event.slug,
|
||||
'organizer': self.event.organizer.slug,
|
||||
}),
|
||||
'data-placeholder': pgettext_lazy('subevent', 'All dates')
|
||||
}
|
||||
)
|
||||
self.fields['subevent'].widget.choices = self.fields['subevent'].choices
|
||||
else:
|
||||
del self.fields['subevent']
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
subevent = cleaned_data.get('subevent')
|
||||
date_range = cleaned_data.get('date_range')
|
||||
|
||||
if subevent is not None and date_range is not None:
|
||||
d_start, d_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), date_range, self.event.timezone)
|
||||
if (
|
||||
(d_start and not (d_start <= subevent.date_from)) or
|
||||
(d_end and not (subevent.date_from < d_end))
|
||||
):
|
||||
self.add_error('subevent', pgettext_lazy('subevent', "Date doesn't start in selected date range."))
|
||||
return cleaned_data
|
||||
|
||||
def filter_qs(self, opqs):
|
||||
fdata = self.cleaned_data
|
||||
|
||||
subevent = fdata.get('subevent', None)
|
||||
date_range = fdata.get('date_range', None)
|
||||
|
||||
if subevent is not None:
|
||||
opqs = opqs.filter(subevent=subevent)
|
||||
|
||||
if date_range is not None:
|
||||
d_start, d_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), date_range, self.event.timezone)
|
||||
opqs = opqs.filter(
|
||||
subevent__date_from__gte=d_start,
|
||||
subevent__date_from__lt=d_end
|
||||
)
|
||||
|
||||
s = fdata.get("status", Order.STATUS_PENDING + Order.STATUS_PAID)
|
||||
if s != "":
|
||||
if s == Order.STATUS_PENDING:
|
||||
opqs = opqs.filter(order__status=Order.STATUS_PENDING,
|
||||
order__expires__lt=now().replace(hour=0, minute=0, second=0))
|
||||
elif s == Order.STATUS_PENDING + Order.STATUS_PAID:
|
||||
opqs = opqs.filter(order__status__in=[Order.STATUS_PENDING, Order.STATUS_PAID])
|
||||
elif s == Order.STATUS_PAID + 'v':
|
||||
opqs = opqs.filter(
|
||||
Q(order__status=Order.STATUS_PAID) |
|
||||
Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True)
|
||||
)
|
||||
elif s == Order.STATUS_PENDING + Order.STATUS_EXPIRED:
|
||||
opqs = opqs.filter(order__status__in=[Order.STATUS_PENDING, Order.STATUS_EXPIRED])
|
||||
else:
|
||||
opqs = opqs.filter(order__status=s)
|
||||
|
||||
if s not in (Order.STATUS_CANCELED, ""):
|
||||
opqs = opqs.filter(canceled=False)
|
||||
if fdata.get("item", "") != "":
|
||||
i = fdata.get("item", "")
|
||||
opqs = opqs.filter(item_id__in=(i,))
|
||||
|
||||
return opqs
|
||||
|
||||
|
||||
class SubEventFilterForm(FilterForm):
|
||||
orders = {
|
||||
'date_from': 'date_from',
|
||||
|
||||
Reference in New Issue
Block a user