mirror of
https://github.com/pretix/pretix.git
synced 2026-08-28 13:34:40 +00:00
New check-in features (#3022)
This commit is contained in:
@@ -340,7 +340,7 @@ class BadgeExporter(BaseExporter):
|
||||
if form_data.get('include_pending'):
|
||||
qs = qs.filter(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
|
||||
else:
|
||||
qs = qs.filter(order__status__in=[Order.STATUS_PAID])
|
||||
qs = qs.filter(Q(order__status=Order.STATUS_PAID) | Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True))
|
||||
|
||||
if form_data.get('date_from'):
|
||||
dt = make_aware(datetime.combine(
|
||||
|
||||
@@ -216,10 +216,13 @@ class CheckInListMixin(BaseExporter):
|
||||
)
|
||||
|
||||
if form_data.get('attention_only'):
|
||||
qs = qs.filter(Q(item__checkin_attention=True) | Q(order__checkin_attention=True))
|
||||
qs = qs.filter(Q(item__checkin_attention=True) | Q(order__checkin_attention=True) | Q(variation__checkin_attention=True))
|
||||
|
||||
if not cl.include_pending:
|
||||
qs = qs.filter(order__status=Order.STATUS_PAID)
|
||||
qs = qs.filter(
|
||||
Q(order__status=Order.STATUS_PAID) |
|
||||
Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True)
|
||||
)
|
||||
else:
|
||||
qs = qs.filter(order__status__in=(Order.STATUS_PAID, Order.STATUS_PENDING))
|
||||
|
||||
@@ -363,12 +366,15 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
)
|
||||
if op.seat:
|
||||
item += '<br/>' + str(op.seat)
|
||||
name = bleach.clean(str(name), tags=['br']).strip().replace('<br>', '<br/>')
|
||||
if op.blocked:
|
||||
name = '<font face="OpenSansBd">[' + _('Blocked') + ']</font> ' + name
|
||||
row = [
|
||||
'!!' if op.item.checkin_attention or op.order.checkin_attention else '',
|
||||
CBFlowable(bool(op.last_checked_in)),
|
||||
'!!' if op.require_checkin_attention else '',
|
||||
CBFlowable(bool(op.last_checked_in)) if not op.blocked else '—',
|
||||
'✘' if op.order.status != Order.STATUS_PAID else '✔',
|
||||
op.order.code,
|
||||
Paragraph(bleach.clean(str(name), tags=['br']).strip().replace('<br>', '<br/>'), self.get_style()),
|
||||
Paragraph(name, self.get_style()),
|
||||
Paragraph(bleach.clean(str(item), tags=['br']).strip().replace('<br>', '<br/>'), self.get_style()),
|
||||
]
|
||||
acache = {}
|
||||
@@ -401,6 +407,12 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
('TEXTCOLOR', (2, len(tdata)), (2, len(tdata)), '#ffffff'),
|
||||
('ALIGN', (2, len(tdata)), (2, len(tdata)), 'CENTER'),
|
||||
]
|
||||
if op.blocked:
|
||||
tstyledata += [
|
||||
('BACKGROUND', (1, len(tdata)), (1, len(tdata)), '#990000'),
|
||||
('TEXTCOLOR', (1, len(tdata)), (1, len(tdata)), '#ffffff'),
|
||||
('ALIGN', (1, len(tdata)), (1, len(tdata)), 'CENTER'),
|
||||
]
|
||||
tdata.append(row)
|
||||
|
||||
table = Table(tdata, colWidths=colwidths, repeatRows=1)
|
||||
@@ -440,7 +452,10 @@ class CSVCheckinList(CheckInListMixin, ListExporter):
|
||||
_('Product'), _('Price'), _('Checked in'), _('Checked out'), _('Automatically checked in')
|
||||
]
|
||||
if not cl.include_pending:
|
||||
qs = qs.filter(order__status=Order.STATUS_PAID)
|
||||
qs = qs.filter(
|
||||
Q(order__status=Order.STATUS_PAID) |
|
||||
Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True)
|
||||
)
|
||||
else:
|
||||
qs = qs.filter(order__status__in=(Order.STATUS_PAID, Order.STATUS_PENDING))
|
||||
headers.append(_('Paid'))
|
||||
@@ -470,6 +485,9 @@ class CSVCheckinList(CheckInListMixin, ListExporter):
|
||||
headers.append(_('Seat zone'))
|
||||
headers.append(_('Seat row'))
|
||||
headers.append(_('Seat number'))
|
||||
headers.append(_('Blocked'))
|
||||
headers.append(_('Valid from'))
|
||||
headers.append(_('Valid until'))
|
||||
headers += [
|
||||
_('Address'),
|
||||
_('ZIP code'),
|
||||
@@ -565,7 +583,7 @@ class CSVCheckinList(CheckInListMixin, ListExporter):
|
||||
row.append(op.voucher.code if op.voucher else "")
|
||||
row.append(op.order.datetime.astimezone(self.event.timezone).strftime('%Y-%m-%d'))
|
||||
row.append(op.order.datetime.astimezone(self.event.timezone).strftime('%H:%M:%S'))
|
||||
row.append(_('Yes') if op.order.checkin_attention or op.item.checkin_attention else _('No'))
|
||||
row.append(_('Yes') if op.require_checkin_attention else _('No'))
|
||||
row.append(op.order.comment or "")
|
||||
|
||||
if op.seat:
|
||||
@@ -580,6 +598,9 @@ class CSVCheckinList(CheckInListMixin, ListExporter):
|
||||
row += ['', '', '', '', '']
|
||||
|
||||
row += [
|
||||
_('Yes') if op.blocked else '',
|
||||
date_format(op.valid_from, 'SHORT_DATETIME_FORMAT') if op.valid_from else '',
|
||||
date_format(op.valid_until, 'SHORT_DATETIME_FORMAT') if op.valid_until else '',
|
||||
op.street or '',
|
||||
op.zipcode or '',
|
||||
op.city or '',
|
||||
|
||||
@@ -243,7 +243,8 @@ class OrderMailForm(BaseMailForm):
|
||||
self.fields['recipients'].choices = recp_choices
|
||||
|
||||
choices = [(e, l) for e, l in Order.STATUS_CHOICE if e != 'n']
|
||||
choices.insert(0, ('na', _('payment pending (except unapproved)')))
|
||||
choices.insert(0, ('valid_if_pending', _('payment pending but already confirmed')))
|
||||
choices.insert(0, ('na', _('payment pending (except unapproved or already confirmed)')))
|
||||
choices.insert(0, ('pa', _('approval pending')))
|
||||
if not event.settings.get('payment_term_expire_automatically', as_type=bool):
|
||||
choices.append(
|
||||
@@ -257,10 +258,11 @@ class OrderMailForm(BaseMailForm):
|
||||
choices=choices
|
||||
)
|
||||
if not self.initial.get('sendto'):
|
||||
self.initial['sendto'] = ['p', 'na']
|
||||
self.initial['sendto'] = ['p', 'na', 'valid_if_pending']
|
||||
elif 'n' in self.initial['sendto']:
|
||||
self.initial['sendto'].append('pa')
|
||||
self.initial['sendto'].append('na')
|
||||
self.initial['sendto'].append('valid_if_pending')
|
||||
|
||||
self.fields['items'].queryset = event.items.all()
|
||||
if not self.initial.get('items'):
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
from datetime import datetime, time, timedelta
|
||||
|
||||
from django.db import models
|
||||
from django.db.models import Exists, OuterRef
|
||||
from django.db.models import Exists, OuterRef, Q
|
||||
from django.utils import timezone
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.timezone import make_aware
|
||||
@@ -118,7 +118,13 @@ class ScheduledMail(models.Model):
|
||||
Exists(OrderPosition.objects.filter(order=OuterRef('pk'), item_id__in=limit_products))
|
||||
)
|
||||
|
||||
status = [Order.STATUS_PENDING, Order.STATUS_PAID] if self.rule.include_pending else [Order.STATUS_PAID]
|
||||
if self.rule.include_pending:
|
||||
status_q = Q(status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
|
||||
else:
|
||||
status_q = Q(
|
||||
Q(status=Order.STATUS_PAID) |
|
||||
Q(status=Order.STATUS_PENDING, valid_if_pending=True)
|
||||
)
|
||||
|
||||
if self.last_successful_order_id:
|
||||
orders = orders.filter(
|
||||
@@ -126,7 +132,7 @@ class ScheduledMail(models.Model):
|
||||
)
|
||||
|
||||
orders = orders.filter(
|
||||
status__in=status,
|
||||
status_q,
|
||||
require_approval=False,
|
||||
).order_by('pk').select_related('invoice_address').prefetch_related('positions')
|
||||
|
||||
|
||||
@@ -264,7 +264,8 @@ class OrderSendView(BaseSenderView):
|
||||
if 'status' not in _cache_store:
|
||||
status = dict(Order.STATUS_CHOICE)
|
||||
status['overdue'] = _('pending with payment overdue')
|
||||
status['na'] = _('payment pending (except unapproved)')
|
||||
status['valid_if_pending'] = _('payment pending but already confirmed')
|
||||
status['na'] = _('payment pending (except unapproved or already confirmed)')
|
||||
status['pa'] = _('approval pending')
|
||||
status['r'] = status['c']
|
||||
_cache_store['status'] = status
|
||||
@@ -346,7 +347,9 @@ class OrderSendView(BaseSenderView):
|
||||
if 'pa' in form.cleaned_data['sendto']:
|
||||
statusq |= Q(status=Order.STATUS_PENDING, require_approval=True)
|
||||
if 'na' in form.cleaned_data['sendto']:
|
||||
statusq |= Q(status=Order.STATUS_PENDING, require_approval=False)
|
||||
statusq |= Q(status=Order.STATUS_PENDING, require_approval=False, valid_if_pending=False)
|
||||
if 'valid_if_pending' in form.cleaned_data['sendto']:
|
||||
statusq |= Q(status=Order.STATUS_PENDING, require_approval=False, valid_if_pending=True)
|
||||
orders = qs.filter(statusq)
|
||||
|
||||
opq = OrderPosition.objects.filter(
|
||||
|
||||
@@ -127,7 +127,7 @@ class AllTicketsPDF(BaseExporter):
|
||||
if form_data.get('include_pending'):
|
||||
qs = qs.filter(order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING])
|
||||
else:
|
||||
qs = qs.filter(order__status__in=[Order.STATUS_PAID])
|
||||
qs = qs.filter(Q(order__status=Order.STATUS_PAID) | Q(order__status=Order.STATUS_PENDING, order__valid_if_pending=True))
|
||||
|
||||
if form_data.get('date_range'):
|
||||
dt_start, dt_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), form_data['date_range'], self.timezone)
|
||||
|
||||
@@ -58,6 +58,8 @@ window.vapp = new Vue({
|
||||
'result.unpaid': gettext('Ticket not paid'),
|
||||
'result.rules': gettext('Entry not allowed'),
|
||||
'result.revoked': gettext('Ticket code revoked/changed'),
|
||||
'result.blocked': gettext('Ticket blocked'),
|
||||
'result.invalid_time': gettext('Ticket not valid at this time'),
|
||||
'result.canceled': gettext('Order canceled'),
|
||||
'result.ambiguous': gettext('Ticket code is ambiguous on list'),
|
||||
'status.checkin': gettext('Checked-in Tickets'),
|
||||
|
||||
Reference in New Issue
Block a user