forked from CGM_Public/pretix_original
Docs: Add algorithm diagrams for checkin
This commit is contained in:
@@ -604,6 +604,8 @@ Order position endpoints
|
|||||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||||
:statuscode 404: The requested order position or check-in list does not exist.
|
:statuscode 404: The requested order position or check-in list does not exist.
|
||||||
|
|
||||||
|
.. _`rest-checkin-redeem`:
|
||||||
|
|
||||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/(id)/redeem/
|
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/(id)/redeem/
|
||||||
|
|
||||||
Tries to redeem an order position, identified by its internal ID, i.e. checks the attendee in. This endpoint
|
Tries to redeem an order position, identified by its internal ID, i.e. checks the attendee in. This endpoint
|
||||||
|
|||||||
28
doc/development/algorithms/checkin.rst
Normal file
28
doc/development/algorithms/checkin.rst
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
.. spelling: libpretixsync
|
||||||
|
|
||||||
|
Check-in algorithms
|
||||||
|
===================
|
||||||
|
|
||||||
|
When a ticket is scanned at the entrance or exit of an event, we follow a series of steps to determine whether
|
||||||
|
the check-in is allowed or not. To understand some of the terms in the following diagrams, you should also check
|
||||||
|
out the documentation of the :ref:`ticket redemption API endpoint <rest-checkin-redeem>`.
|
||||||
|
|
||||||
|
Server-side
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The following diagram shows the series of checks executed on the server when a ticket is redeemed through the API.
|
||||||
|
Some simplifications have been made, for example the de-duplication mechanism based on the ``nonce`` parameter
|
||||||
|
to prevent re-uploads of the same scan is not shown.
|
||||||
|
|
||||||
|
.. image:: /images/checkin_online.png
|
||||||
|
|
||||||
|
Client-side
|
||||||
|
-----------
|
||||||
|
|
||||||
|
The process of verifying tickets offline is a little different. There are two different approaches,
|
||||||
|
depending on whether we have information about all tickets in the local database. The following diagram shows
|
||||||
|
the algorithm as currently implemented in recent versions of `libpretixsync`_.
|
||||||
|
|
||||||
|
.. image:: /images/checkin_offline.png
|
||||||
|
|
||||||
|
.. _libpretixsync: https://github.com/pretix/libpretixsync
|
||||||
13
doc/development/algorithms/index.rst
Normal file
13
doc/development/algorithms/index.rst
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Algorithms
|
||||||
|
==========
|
||||||
|
|
||||||
|
The business logic inside pretix is full of complex algorithms making decisions based on all the hundreds of settings
|
||||||
|
and input parameters available. Some of them are documented here as graphs, either because fully understanding them is very
|
||||||
|
when working on features close to them, or because they also need to be re-implemented by client-side components like our
|
||||||
|
ticket scanning apps and we want to ensure the implementations are as similar as possible to avoid confusion.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
checkin
|
||||||
|
layouts
|
||||||
15
doc/development/algorithms/layouts.rst
Normal file
15
doc/development/algorithms/layouts.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.. spelling: pretixPOS
|
||||||
|
|
||||||
|
Ticket layout
|
||||||
|
=============
|
||||||
|
|
||||||
|
When a ticket is exported to PDF, the system needs to decide which of multiple PDF layouts to use. The
|
||||||
|
following diagram shows the steps of the decision, showing both the implementation in pretix itself as
|
||||||
|
well as the implementation in `pretixPOS`_.
|
||||||
|
|
||||||
|
The process can be influenced by plugins, which is demonstrated with the example of the shipping plugin.
|
||||||
|
|
||||||
|
.. image:: /images/ticket_layouts.png
|
||||||
|
|
||||||
|
|
||||||
|
.. _pretixPOS: https://pretix.eu/about/en/pos
|
||||||
@@ -8,6 +8,7 @@ Developer documentation
|
|||||||
setup
|
setup
|
||||||
contribution/index
|
contribution/index
|
||||||
implementation/index
|
implementation/index
|
||||||
translation/index
|
algorithms/index
|
||||||
api/index
|
api/index
|
||||||
structure
|
structure
|
||||||
|
translation/index
|
||||||
|
|||||||
BIN
doc/images/checkin_offline.png
Normal file
BIN
doc/images/checkin_offline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 236 KiB |
146
doc/images/checkin_offline.puml
Normal file
146
doc/images/checkin_offline.puml
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
@startuml
|
||||||
|
|
||||||
|
|
||||||
|
partition "data-based check" {
|
||||||
|
"Check based on local database" --> "Is the order in status PAID or PENDING\nand is the position not canceled?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error CANCELED"
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the product part of the check-in list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error PRODUCT"
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the subevent part of the check-in list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error INVALID"
|
||||||
|
note bottom: TODO\ninconsistent\nwith online\ncheck
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the order in status PAID?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Does the check-in list include pending orders?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error UNPAID "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is ignore_unpaid set?\n(Has the operator confirmed\nthe checkin?)"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error UNPAID "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is this an entry or exit?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-down->[yes] "Is this an entry or exit?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Is this an entry or exit?" --> if "" then
|
||||||
|
-right->[entry] Evaluate custom logic (rules)
|
||||||
|
--> if "" then
|
||||||
|
-right->[error] "Return error RULES"
|
||||||
|
else
|
||||||
|
-down->[ok] "Are all required questions answered?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error INCOMPLETE"
|
||||||
|
else
|
||||||
|
-down->[yes] "Does the check-in list allow multi-entry?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-->[exit] "Return OK "
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Does the check-in list allow multi-entry?" --> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Is this the first checkin\nfor this ticket on this list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Are all previous checkins\nfor this ticket on this list exits?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Does the check-in list\n allow entry after exit\nand is the last checkin\nan exit?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Return error ALREADY_REDEEMED"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
partition "dataless check" {
|
||||||
|
"Check based on secret content" --> "Does the secret decode with\nany supported scheme\nand has a valid signature?"
|
||||||
|
|
||||||
|
--> if "" then
|
||||||
|
-down->[yes] "Is the ticket secret on the revocation list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return error REVOKED"
|
||||||
|
else
|
||||||
|
-down->[no] "Is the product part of the check-in list? "
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error PRODUCT "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the subevent part of the check-in list? "
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error INVALID "
|
||||||
|
note bottom: TODO\ninconsistent\nwith online\ncheck
|
||||||
|
else
|
||||||
|
--> "Is this an entry or exit? "
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-right>[no] "Return error INVALID "
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Is this an entry or exit? " --> if "" then
|
||||||
|
-right->[entry] "Evaluate custom logic (rules) "
|
||||||
|
--> if "" then
|
||||||
|
-right->[error] "Return error RULES "
|
||||||
|
else
|
||||||
|
-down->[ok] "Are all required questions answered? "
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error INCOMPLETE "
|
||||||
|
else
|
||||||
|
-down->[yes] "Does the check-in list allow multi-entry? "
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-->[exit] " Return OK "
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Does the check-in list allow multi-entry? " --> if "" then
|
||||||
|
-right->[yes] " Return OK "
|
||||||
|
else
|
||||||
|
-down->[no] "Are any locally queued checkins for\nthis ticket of this list known?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] " Return OK "
|
||||||
|
else
|
||||||
|
-down->[yes] "Are all locally queued checkins\nfor this ticket on this list exits? "
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] " Return OK "
|
||||||
|
else
|
||||||
|
-down->[no] "Does the check-in list\n allow entry after exit\nand is the last locally\nqueued checkin\nan exit? "
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] " Return OK "
|
||||||
|
else
|
||||||
|
-down->[no] "Return error ALREADY_REDEEMED "
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
(*) --> "Check if order position with\nscanned ticket secret exists"
|
||||||
|
--> if "" then
|
||||||
|
-down->[yes] "Check based on local database"
|
||||||
|
else
|
||||||
|
-->[no] "Check based on secret content"
|
||||||
|
endif
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
doc/images/checkin_online.png
Normal file
BIN
doc/images/checkin_online.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
92
doc/images/checkin_online.puml
Normal file
92
doc/images/checkin_online.puml
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@startuml
|
||||||
|
|
||||||
|
(*) --> "Check if order position with\nscanned ticket secret exists"
|
||||||
|
--> if "" then
|
||||||
|
-down->[yes] ===CHECK===
|
||||||
|
else
|
||||||
|
-->[no] "Check if secret exists\nin revocation list"
|
||||||
|
--> if "" then
|
||||||
|
--> "Is this a forced upload?"
|
||||||
|
--> if "" then
|
||||||
|
-->[yes] ===CHECK===
|
||||||
|
else
|
||||||
|
-right->[no] "Return error REVOKED"
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-right->[no] "Return error INVALID"
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
===CHECK=== -down-> "Is the order in status PAID or PENDING\nand is the position not canceled?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error CANCELED"
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the product part of the check-in list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error PRODUCT"
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the subevent part of the check-in list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error PRODUCT "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is the order in status PAID\nor is this a forced upload?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Does the check-in list include pending orders?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error UNPAID "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is ignore_unpaid set?\n(Has the operator confirmed\nthe checkin?)"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no] "Return error UNPAID "
|
||||||
|
else
|
||||||
|
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-down->[yes] "Is this an entry or exit?\nIs the upload forced?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Is this an entry or exit?\nIs the upload forced?" --> if "" then
|
||||||
|
-right->[entry && not force] Evaluate custom logic (rules)
|
||||||
|
--> if "" then
|
||||||
|
-right->[error] "Return error RULES"
|
||||||
|
else
|
||||||
|
-down->[ok] "Are all required questions answered?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[no && questions_supported] "Return error INCOMPLETE"
|
||||||
|
else
|
||||||
|
-down->[yes || not questions_supported] "Does the check-in list allow multi-entry?"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
-->[exit || force=true] "Return OK "
|
||||||
|
endif
|
||||||
|
|
||||||
|
"Does the check-in list allow multi-entry?" --> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Is this the first checkin\nfor this ticket on this list?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Are all previous checkins\nfor this ticket on this list exits?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Does the check-in list\n allow entry after exit\nand is the last checkin\nan exit?"
|
||||||
|
--> if "" then
|
||||||
|
-right->[yes] "Return OK"
|
||||||
|
else
|
||||||
|
-down->[no] "Return error ALREADY_REDEEMED"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
doc/images/ticket_layouts.png
Normal file
BIN
doc/images/ticket_layouts.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
52
doc/images/ticket_layouts.puml
Normal file
52
doc/images/ticket_layouts.puml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
@startuml
|
||||||
|
|
||||||
|
(*) --> "Which implementation?"
|
||||||
|
--> if "" then
|
||||||
|
-down->[pretixPOS] "Check for TicketLayoutItem with\nsales_channel=pretixpos [libpretixsync]"
|
||||||
|
--> if "" then
|
||||||
|
--> (*)
|
||||||
|
else
|
||||||
|
-->[not found] "Check for TicketLayoutItem with\nsales_channel=web [libpretixsync]"
|
||||||
|
--> if "" then
|
||||||
|
--> (*)
|
||||||
|
else
|
||||||
|
-->[not found] "Use event default [libpretixsync]"
|
||||||
|
--> (*)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
-right->[pretix] "Check for TicketLayoutItem with\nsales_channel=order.sales_channel"
|
||||||
|
--> if "" then
|
||||||
|
-right-> "Run override_layout plugin signal on result"
|
||||||
|
else
|
||||||
|
-down->[not found] "Check for TicketLayoutItem with\nsales_channel=web"
|
||||||
|
--> if "" then
|
||||||
|
--> "Run override_layout plugin signal on result"
|
||||||
|
else
|
||||||
|
-->[not found] "Use event default"
|
||||||
|
--> "Run override_layout plugin signal on result"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
"Run override_layout plugin signal on result" -> (*)
|
||||||
|
|
||||||
|
|
||||||
|
partition pretix_shipping {
|
||||||
|
"Run override_layout plugin signal on result" --> "Check for ShippingLayoutItem with\nmethod=order.shipping_method"
|
||||||
|
--> if "" then
|
||||||
|
--> (*)
|
||||||
|
else
|
||||||
|
-down->[not found] "Check for ShippingMethod.layout"
|
||||||
|
--> if "" then
|
||||||
|
--> (*)
|
||||||
|
else
|
||||||
|
-down->[not found] "Keep original layout"
|
||||||
|
--> (*)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@enduml
|
||||||
@@ -597,6 +597,11 @@ def perform_checkin(op: OrderPosition, clist: CheckinList, given_answers: dict,
|
|||||||
:param nonce: A random nonce to prevent race conditions.
|
:param nonce: A random nonce to prevent race conditions.
|
||||||
:param datetime: The datetime of the checkin, defaults to now.
|
:param datetime: The datetime of the checkin, defaults to now.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# !!!!!!!!!
|
||||||
|
# Update doc/images/checkin_online.puml if you make substantial changes here!
|
||||||
|
# !!!!!!!!!
|
||||||
|
|
||||||
dt = datetime or now()
|
dt = datetime or now()
|
||||||
|
|
||||||
if op.canceled or op.order.status not in (Order.STATUS_PAID, Order.STATUS_PENDING):
|
if op.canceled or op.order.status not in (Order.STATUS_PAID, Order.STATUS_PENDING):
|
||||||
|
|||||||
Reference in New Issue
Block a user