mirror of
https://github.com/pretix/pretix.git
synced 2026-08-11 10:57:00 +00:00
Update documentation
This commit is contained in:
+11
-5
@@ -104,7 +104,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'haiku'
|
||||
#html_theme = ""
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@@ -156,10 +156,10 @@ html_static_path = ['_static']
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
html_domain_indices = False
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
html_use_index = False
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
@@ -184,15 +184,21 @@ html_static_path = ['_static']
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'tixldoc'
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
'papersize': 'a4paper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
|
||||
+106
-19
@@ -4,46 +4,133 @@ Implementation Concepts
|
||||
Basic terminology
|
||||
-----------------
|
||||
|
||||
The components
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The project tixl is split into several components. The main three of them are:
|
||||
|
||||
**tixlbase**
|
||||
Tixlbase is the foundation below all other components. It is primarily
|
||||
responsible for the data structures and database communication. It also hosts
|
||||
several utilities which are used by multiple other components.
|
||||
|
||||
**tixlcontrol**
|
||||
Tixlcontrol is the web-based backend software which allows organizers to
|
||||
create and manage their events, items, orders and tickets.
|
||||
|
||||
**tixlpresale**
|
||||
Tixlpresale is the ticket-shop itself, containing all the parts visible to the
|
||||
end user.
|
||||
|
||||
Users and events
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Tixl is all about **events**, which are defined as something happening somewhere. Every Event is managed by the **organizer**, an abstract entity running the event.
|
||||
Tixl is all about **events**, which are defined as something happening somewhere.
|
||||
Every Event is managed by the **organizer**, an abstract entity running the event.
|
||||
|
||||
Tixl is used by **users**, of which it knows two types:
|
||||
Tixl is used by **users**. We want to enable global users who can just login into
|
||||
tixl and buy tickets for as many events as they like but at the same time it
|
||||
should be possible to create some kind of local user to have a temporary account
|
||||
just to buy tickets for one single event.
|
||||
|
||||
The problem is, we cannot use usernames as primary keys for our users, as we
|
||||
do not want one username to be blocked forever just because of one temporary
|
||||
account using it (people would have to think of a new username for every temporary
|
||||
account they create). On the other hand, we can not use e-mail addresses either,
|
||||
as those are not unique (imagine one person having multiple temporary accounts)
|
||||
and they should not be required for temporary account (to enable anonymity).
|
||||
|
||||
Therefore, we split our users into two groups and use an internal **identifier**
|
||||
as our primary key:
|
||||
|
||||
**Local users**
|
||||
Local users do only exist inside the scope of one event. They are identified by usernames, which are only valid for exactly one event.
|
||||
Local users do only exist inside the scope of one event. They are identified by
|
||||
usernames, which are only valid for exactly one event. Internally, their identifier
|
||||
is "{username}@{event.id}.event.tixl"
|
||||
|
||||
**Global users**
|
||||
Global users exist everywhere in the installation of Tixl. They can buy tickets for multiple events and they can be managers of one or more Organizers/Events. Global users are identified by e-mail addresses.
|
||||
Global users exist everywhere in the installation of Tixl. They can buy tickets
|
||||
for multiple events and they can be managers of one or more Organizers/Events.
|
||||
Global users are identified by e-mail addresses.
|
||||
|
||||
For more information about this user concept and reasons behind it, see the docstring of the ``tixlbase.models.User`` class.
|
||||
|
||||
Items and variations
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The purpose of tixl is to sell **items** (which belong to **events**) to **users**. An **item** is a abstract thing, popular examples being event tickets or a piece of merchandise, like 'T-Shirt'. An **item** can have multiple **properties** with multiple **values** each. For example, the **item** 'T-Shirt' could have the **property** 'Size' with **values** 'S', 'M' and 'L' and the **property** 'Color' with **values** 'black' and 'blue'.
|
||||
The purpose of tixl is to sell **items** (which belong to **events**) to **users**.
|
||||
An **item** is a abstract thing, popular examples being event tickets or a piece of
|
||||
merchandise, like 'T-Shirt'. An **item** can have multiple **properties** with multiple
|
||||
**values** each. For example, the **item** 'T-Shirt' could have the **property** 'Size'
|
||||
with **values** 'S', 'M' and 'L' and the **property** 'Color' with **values** 'black'
|
||||
and 'blue'.
|
||||
|
||||
Any combination of those **values** is called a **variation**. Using the examples from above, a possible **variation** would be 'T-Shirt S blue'.
|
||||
Any combination of those **values** is called a **variation**. Using the examples from
|
||||
above, a possible **variation** would be 'T-Shirt, S, blue'.
|
||||
|
||||
Restrictions
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The probably most powerful concepts of tixl is the very abstract concept of **restricitons**. We already know that **items** can come in very different **variations**, but a **restriction** decides whether an item is available for sale and assign **prices** to **variations**. There are **restriction types**, which are pieces of code implementing the restrictions and **restriction instances**, which are configurations made by the **organzier**. Although **restrictions** are a very abstract concept which can be used to do nearly anything, there are a few obvious examples:
|
||||
The probably most powerful concepts of tixl is the very abstract concept of **restricitons**.
|
||||
We already know that **items** can come in very different **variations**, but a
|
||||
**restriction** decides whether an variation is available for sale and assign **prices**
|
||||
to **variations**. There are **restriction types** (pieces of code implementing the
|
||||
restriction logic) and **restriction instances** (the specific configurations made by the
|
||||
organzier). Although **restrictions** are a very abstract concept which can be used
|
||||
to do nearly anything, there are a few obvious examples:
|
||||
|
||||
* One easy example is the time restriction, which allows the sale of certain item variations only within a certain time frame. As restrictions can also assign a price to a variation, this can also be used to implement something like 'early-bird prices' for your tickets by using multiple time restrictions with different prices.
|
||||
* The most obvious example is the number restriction, which limits the sale of the tickets to a maximum number. You can use this either to stop selling tickets completely when your house is full or for creating limited 'VIP tickets'.
|
||||
* A more advanced example is a restriction by user, for example reduced ticket prices for members who are members of a special group.
|
||||
* Arbitrary sophisticated features like coupon codes are also possible to be implemented using this feature.
|
||||
* One easy example is a restriction by time, which allows the sale of certain item variations
|
||||
only within a certain time frame. As restrictions can also assign a price to a variation,
|
||||
this can also be used to implement something like 'early-bird prices' for your tickets by
|
||||
using multiple time restrictions with different prices.
|
||||
* The most obvious example is the restriction by number, which limits the sale of the tickets to
|
||||
a maximum number. You can use this either to stop selling tickets completely when your house
|
||||
is full or for creating limited 'VIP tickets'. We'll come to this again later.
|
||||
* A more advanced example is a restriction by user, for example reduced ticket prices for
|
||||
members who are members of a special group.
|
||||
* Arbitrary sophisticated features like coupon codes are also possible to be implemented using
|
||||
this feature.
|
||||
|
||||
Any number of **restrictions** can be applied to the whole of a **item** or to a specific **variation**. The processing of the restriction follows the following set of rules:
|
||||
Any number of **restrictions** can be applied to the whole of a **item** or even to a specific
|
||||
**variation**. The processing of the restriction follows the following set of rules:
|
||||
|
||||
* **Variation**-specific rules have precedence over **item**-specific rules.
|
||||
* The restrictions are being processed in random order (there may not be any assumptions about the evaluation order).
|
||||
* Multiple restriction instances of **different restriction types** are linked with *and*, so if both a time frame and a number restriction are applied to an item, the item is only avaliable for sale within the given time frame *and* only as long as items are available.
|
||||
* Multiple restriction instances of the **same restriction type** are linked with *or*, so if two time frames are applied to an item, the item is available for sale in both of the time frames. (This behaviour is actually a decision of the restriction type itself, so this rule is not enforced but rather a general rule of thumb).
|
||||
* Variation-specific rules have precedence over item-specific rules.
|
||||
* The restrictions are being processed in random order (there may not be any assumptions about
|
||||
the evaluation order).
|
||||
* Multiple restriction instances of **different restriction types** are linked with *and*, so
|
||||
if both a time frame and a restriction by number are applied to an item, the item is only avaliable
|
||||
for sale during the given time frame *and* only as long as items are available.
|
||||
* Multiple restriction instances of the **same restriction type** are typically linked with *or*,
|
||||
although this is the decision of the restriction logic itself and not mandatory. So for example
|
||||
the restriction by time would implement this default logic, because if two time frames are applied
|
||||
to an item, the item should be available for sale in both of the time frames (it just does not make
|
||||
sense otherwise on an one-dimensional time axis).
|
||||
* If multiple restrictions apply which set the price, the *cheapest* price determines the final price.
|
||||
|
||||
Restriction types can be introduced by 3rd-party code and do not require changes to the tixl codebase.
|
||||
Restrictions can be implemented using a plugin system and do not require changes to the tixl codebase.
|
||||
|
||||
.. note:: This pluggability of restrictions is implemented using the 'signal and receiver' pattern provided by Django. Restrictions can therefore live in seperate Django apps.
|
||||
Restriction by number
|
||||
"""""""""""""""""""""
|
||||
|
||||
The restriction by number is a special case, as it is the only (planned) restriction type demanding
|
||||
special care in the implementation to never sell more tickets than allowed, even under heavy load.
|
||||
|
||||
* There is a concept of **quotas**. A quota is basically a number of items combined with information
|
||||
about how many of them are still available.
|
||||
* Every time a user places a item in the cart, a **lock** object is created, reducing the number of
|
||||
available items in the pool by one. The lock is valid for a fixed time (e.g. 30 minutes), but not
|
||||
instantly deleted afther those 30 minutes (we'll get to that).
|
||||
* Every time a user places a binding order, the lock object is replaced by an **order** which behaves
|
||||
much the same as the lock. It reduces the number of available item and is valid for a fixed time, this
|
||||
time for the configured payment term (e.g. 14 days).
|
||||
* If the order is being paid, the **order** becomes permanent.
|
||||
* Once there are no available tickets left and a user wants to buy a ticket, a lock which is in place
|
||||
for more than the allowed time frame is being removed in favor of the new buyer. If there are no
|
||||
abandoned locks available, an unpaid order being older than the configured payment term is being
|
||||
removed. If there are none of them as well, this quota is sold out.
|
||||
* The same quota can apply to multiple items and one item can be affected by multiple quotas, to
|
||||
enable both of the following features at the same time:
|
||||
|
||||
* You'll want to make sure you never have more then X people at your event, so you'll create a quota
|
||||
applying to all ticket items.
|
||||
* You want to reduce the first Y tickets in price, so you'll create a restriction which is bound by
|
||||
a quota of Y and reduces the price.
|
||||
|
||||
+37
-12
@@ -8,8 +8,8 @@ Just clone our git repository including its submodules::
|
||||
git clone --recursive https://github.com/tixl/tixl.git
|
||||
cd tixl/
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
External Dependencies
|
||||
---------------------
|
||||
* Python 3.4 or newer
|
||||
* ``pip`` for Python 3
|
||||
* ``git``
|
||||
@@ -18,12 +18,17 @@ Dependencies
|
||||
Your local python environment
|
||||
-----------------------------
|
||||
|
||||
Please execute ``python -V`` or ``python3 -V`` to make sure you have Python 3.4 installed. Also make sure you have pip for Python 3 installed, you can execute ``pip3 -V`` to check. Then use Python 3.4's internal tools to create a virtual environment and activate it for your current session::
|
||||
Please execute ``python -V`` or ``python3 -V`` to make sure you have Python 3.4
|
||||
installed. Also make sure you have pip for Python 3 installed, you can execute
|
||||
``pip3 -V`` to check. Then use Python 3.4's internal tools to create a virtual
|
||||
environment and activate it for your current session::
|
||||
|
||||
pyvenv env
|
||||
source env/bin/activate
|
||||
|
||||
You should now see a ``(env)`` prepended to your shell prompt.
|
||||
You should now see a ``(env)`` prepended to your shell prompt. You have to do this
|
||||
in every shell you use to work with tixl (or configure your shell to do so
|
||||
automatically).
|
||||
|
||||
Working with the code
|
||||
---------------------
|
||||
@@ -38,33 +43,53 @@ Then, create the local database::
|
||||
|
||||
Create the translation files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
To generate updated translation files, run a::
|
||||
If you're working with the translation, you can use the following command to scan the
|
||||
source code for strings to be translated and update the ``*.po`` files accordingly::
|
||||
|
||||
make localegen
|
||||
|
||||
To compile the language files for use, run::
|
||||
To actually see tixl in your language, you have to compile the ``*.po`` files to their
|
||||
optimized binary ``*.mo`` counterparts::
|
||||
|
||||
make localecompile
|
||||
|
||||
Run the development server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Execute::
|
||||
To run the local development webserver, execute::
|
||||
|
||||
python manage.py runserver
|
||||
|
||||
to start a local development webserver on port 8000.
|
||||
and head to http://localhost:8000/
|
||||
|
||||
Static code checks
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Code checks and unit tests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Before you check in your code into git, always run::
|
||||
|
||||
flake8 .
|
||||
python manage.py validate
|
||||
python manage.py test
|
||||
|
||||
to check for syntax, style and other errors. The ``flake8`` command by default is a bit
|
||||
stricter than what we really enforce, but we do enforce that all commits produce no output
|
||||
from::
|
||||
|
||||
flake8 --ignore=E123,E128,F403,F401,N802 .
|
||||
|
||||
It is therefore a good idea to put this command into your git hook ``.git/hooks/pre-commit``,
|
||||
for example::
|
||||
|
||||
#!/bin/sh
|
||||
cd $GIT_DIR/../src
|
||||
source ../env/bin/activate
|
||||
flake8 --ignore=E123,E128,F403,F401,N802 .
|
||||
|
||||
|
||||
to check for syntax, style and other errors.
|
||||
|
||||
Working with the documentation
|
||||
------------------------------
|
||||
First, you should install the requiremente necessary for building the documentation. Make sure you have your virtual python enviroment activated (see above). Then, install the packages by executing::
|
||||
First, you should install the requirements necessary for building the documentation.
|
||||
Make sure you have your virtual python enviroment activated (see above). Then, install the
|
||||
packages by executing::
|
||||
|
||||
cd doc/
|
||||
pip install -r requirements.txt
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
Sphinx
|
||||
markupsafe
|
||||
sphinx_rtd_theme
|
||||
|
||||
Reference in New Issue
Block a user