Compare commits

...

1 Commits

Author SHA1 Message Date
Raphael Michel
8759477cf5 Check-in: New scan type "print" 2023-08-11 14:48:23 +02:00
7 changed files with 26 additions and 7 deletions

View File

@@ -34,7 +34,7 @@ Checking a ticket in
:<json string secret: Scanned QR code corresponding to the ``secret`` attribute of a ticket.
:<json string source_type: Type of source the ``secret`` was obtained form. Defaults to ``"barcode"``.
:<json array lists: List of check-in list IDs to search on. No two check-in lists may be from the same event.
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry, ``"print"`` for a badge print scan.
:<json datetime datetime: Specifies the datetime of the check-in. If not supplied, the current time will be used.
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
questions that have not been filled. This is usually used to upload offline scans that already happened,

View File

@@ -631,7 +631,7 @@ Order position endpoints
:<json boolean force: Specifies that the check-in should succeed regardless of revoked barcode, previous check-ins or required
questions that have not been filled. This is usually used to upload offline scans that already happened,
because there's no point in validating them since they happened whether they are valid or not. Defaults to ``false``.
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry.
:<json string type: Send ``"exit"`` for an exit and ``"entry"`` (default) for an entry, ``"print"`` for a badge print scan.
:<json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
Defaults to ``false`` and only works when ``include_pending`` is set on the check-in
list.

View File

@@ -179,7 +179,7 @@ class CheckinList(LoggedModel):
# dedupliate by position and count it up.
cl = self
base_q, base_params = (
Checkin.all.filter(*c_q, successful=True, list=cl)
Checkin.all.filter(*c_q, successful=True, list=cl, type__in=[Checkin.TYPE_ENTRY, Checkin.TYPE_EXIT])
.annotate(
cnt_exists_after=Window(
expression=Count("position_id", filter=Q(type=Value("exit"))),
@@ -322,9 +322,11 @@ class Checkin(models.Model):
"""
TYPE_ENTRY = 'entry'
TYPE_EXIT = 'exit'
TYPE_PRINT = 'print'
CHECKIN_TYPES = (
(TYPE_ENTRY, _('Entry')),
(TYPE_EXIT, _('Exit')),
(TYPE_PRINT, _('Print')),
)
REASON_CANCELED = 'canceled'

View File

@@ -773,7 +773,7 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
'blocked'
)
if type != Checkin.TYPE_EXIT and op.valid_from and op.valid_from > dt:
if type not in (Checkin.TYPE_PRINT, Checkin.TYPE_EXIT) and op.valid_from and op.valid_from > dt:
if force:
force_used = True
else:
@@ -787,7 +787,7 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
),
)
if type != Checkin.TYPE_EXIT and op.valid_until and op.valid_until < dt:
if type not in (Checkin.TYPE_PRINT, Checkin.TYPE_EXIT) and op.valid_until and op.valid_until < dt:
if force:
force_used = True
else:
@@ -886,9 +886,9 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
if isinstance(auth, Device):
device = auth
last_cis = list(op.checkins.order_by('-datetime').filter(list=clist).only('type', 'nonce'))
last_cis = list(op.checkins.order_by('-datetime').filter(list=clist, type__in=(Checkin.TYPE_ENTRY, Checkin.TYPE_EXIT)).only('type', 'nonce'))
entry_allowed = (
type == Checkin.TYPE_EXIT or
type in (Checkin.TYPE_EXIT, Checkin.TYPE_PRINT) or
clist.allow_multiple_entries or
not last_cis or
all(c.type == Checkin.TYPE_EXIT for c in last_cis) or

View File

@@ -295,6 +295,20 @@ def _display_checkin(event, logentry):
posid=data.get('positionid'),
list=checkin_list
)
if data.get('type') == Checkin.TYPE_PRINT:
if show_dt:
return _('Position #{posid} has been printed out at {datetime} for list "{list}".').format(
posid=data.get('positionid'),
datetime=dt_formatted,
list=checkin_list
)
else:
return _('Position #{posid} has been printed out for list "{list}".').format(
posid=data.get('positionid'),
list=checkin_list
)
if data.get('first'):
if show_dt:
return _('Position #{posid} has been checked in at {datetime} for list "{list}".').format(

View File

@@ -95,6 +95,7 @@
<td>
{% if c.type == "exit" %}<span class="fa fa-fw fa-sign-out"></span>{% endif %}
{% if c.type == "entry" %}<span class="fa fa-fw fa-sign-in"></span>{% endif %}
{% if c.type == "print" %}<span class="fa fa-fw fa-print"></span>{% endif %}
{{ c.get_type_display }}
<br>
<small>

View File

@@ -385,6 +385,8 @@
{% else %}
<span class="fa fa-fw text-success fa-sign-out" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Exit scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% endif %}
{% elif c.type == "print" %}
<span class="fa fa-fw text-success fa-print" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Print scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% elif c.forced %}
<span class="fa fa-fw fa-warning text-warning" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Additional entry scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% elif c.auto_checked_in %}