Compare commits
1711 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91c02dc0b3 | ||
|
|
f78ec830b5 | ||
|
|
9f0e508ab3 | ||
|
|
4ca50d750b | ||
|
|
07c1b1b7f3 | ||
|
|
3e95dd52cf | ||
|
|
80ef2f6b0e | ||
|
|
53a8cda310 | ||
|
|
63de49104c | ||
|
|
8aa80bcb84 | ||
|
|
95115a7c5e | ||
|
|
ce2967fd02 | ||
|
|
399fb87d20 | ||
|
|
c4bd5ac5df | ||
|
|
123c2d6c02 | ||
|
|
6954e9c984 | ||
|
|
fc573e4e48 | ||
|
|
0dbcfdc5ac | ||
|
|
4b8d4b4792 | ||
|
|
d798da33ef | ||
|
|
d99517c8d1 | ||
|
|
0787adcb8e | ||
|
|
f848561d25 | ||
|
|
efbddc2486 | ||
|
|
e6a138d8f2 | ||
|
|
5b7a578307 | ||
|
|
737738de93 | ||
|
|
eb3951ce13 | ||
|
|
c2b7d9a257 | ||
|
|
4738aa2771 | ||
|
|
29ac0af55e | ||
|
|
96bc64c456 | ||
|
|
0369deb72d | ||
|
|
6e53990845 | ||
|
|
feb262644e | ||
|
|
abd679820f | ||
|
|
cd3ce848d1 | ||
|
|
63ba393c12 | ||
|
|
23fdf8c457 | ||
|
|
304ad4e3db | ||
|
|
ec58ab07b6 | ||
|
|
1ba4047b1b | ||
|
|
0bab8adc41 | ||
|
|
17e09c601e | ||
|
|
1aca5fb6ff | ||
|
|
7860d690fa | ||
|
|
6d01c99d38 | ||
|
|
ddb645aeea | ||
|
|
f08e4b41c4 | ||
|
|
1e23624955 | ||
|
|
ee951a7448 | ||
|
|
9935ba370d | ||
|
|
e815cce143 | ||
|
|
cea1032180 | ||
|
|
5695e1d9c8 | ||
|
|
fd317afd01 | ||
|
|
ccddd2a96f | ||
|
|
513d3034d8 | ||
|
|
51495187fa | ||
|
|
2bd53f7b9f | ||
|
|
06d9c48ed4 | ||
|
|
1155d18b7f | ||
|
|
6e14592c78 | ||
|
|
55feaf2d2c | ||
|
|
c487036c8b | ||
|
|
853ebf8c70 | ||
|
|
1c695c1cf9 | ||
|
|
bd5687d169 | ||
|
|
b384f71b64 | ||
|
|
10dd5278e7 | ||
|
|
befa6527e4 | ||
|
|
00497630cb | ||
|
|
95cd457de1 | ||
|
|
7518c9e3e0 | ||
|
|
6a999835e2 | ||
|
|
41d099c1be | ||
|
|
ff306ce2c5 | ||
|
|
c7abc82055 | ||
|
|
041d91dd3c | ||
|
|
387f56ed9b | ||
|
|
3181323c1f | ||
|
|
ecf84150c1 | ||
|
|
5b5025c776 | ||
|
|
e47dd3058b | ||
|
|
71f1dcd475 | ||
|
|
941856932c | ||
|
|
c51fde52e7 | ||
|
|
c5362e3bde | ||
|
|
a113703451 | ||
|
|
55ecb918e9 | ||
|
|
3a870e2f8b | ||
|
|
734231a4f1 | ||
|
|
223d6b29f4 | ||
|
|
4f41ec0a97 | ||
|
|
347a53297d | ||
|
|
820766abcb | ||
|
|
4974fa1fed | ||
|
|
7e829fa204 | ||
|
|
f6c7caa48d | ||
|
|
0dd9d252fd | ||
|
|
39f67a241c | ||
|
|
5706b08366 | ||
|
|
81de9695e2 | ||
|
|
589fb25fe3 | ||
|
|
61e5c6b468 | ||
|
|
087ceb3687 | ||
|
|
0a2cd208b2 | ||
|
|
678a936897 | ||
|
|
7c72ca089b | ||
|
|
21530f315f | ||
|
|
7274905a92 | ||
|
|
6c5cff6162 | ||
|
|
cf6b6c129a | ||
|
|
74491d16ae | ||
|
|
c1ab6e4eb4 | ||
|
|
18c9ae235a | ||
|
|
5c69d5fb88 | ||
|
|
90f0bda879 | ||
|
|
1b5c4a21bb | ||
|
|
08ee37112f | ||
|
|
cfbc88d3d6 | ||
|
|
79f5529a5a | ||
|
|
11ed0abd18 | ||
|
|
01830d9910 | ||
|
|
0f573805f2 | ||
|
|
93b1d81a48 | ||
|
|
e28d13b910 | ||
|
|
8731e343c4 | ||
|
|
605eca8cd7 | ||
|
|
5a8ddf5e4a | ||
|
|
f6d5d575fc | ||
|
|
d5c344e3ac | ||
|
|
18ba326cea | ||
|
|
1a1473d3ba | ||
|
|
72804a09ec | ||
|
|
c1ce0a514c | ||
|
|
bd479312b5 | ||
|
|
469da540d2 | ||
|
|
69edaa974f | ||
|
|
ff56963040 | ||
|
|
266aeaef50 | ||
|
|
fc660cfb1f | ||
|
|
27d343bdea | ||
|
|
a04b0da54a | ||
|
|
b15a6bfa98 | ||
|
|
dcc638c12f | ||
|
|
84ea96a5ad | ||
|
|
ae1bf85740 | ||
|
|
1612d713c9 | ||
|
|
6a4a8af731 | ||
|
|
e18375ca6d | ||
|
|
e537e4538a | ||
|
|
1ae97f5477 | ||
|
|
cc0083c6e5 | ||
|
|
43e6ed2da9 | ||
|
|
27bb3a948b | ||
|
|
7c155d307b | ||
|
|
d789beddd0 | ||
|
|
f790148ad3 | ||
|
|
a643abe293 | ||
|
|
099b08f009 | ||
|
|
35ddf6790e | ||
|
|
6502fdb1f5 | ||
|
|
b5cd3bf0af | ||
|
|
8183648902 | ||
|
|
0e1159b01e | ||
|
|
625ef3da8a | ||
|
|
10c7d9a6e1 | ||
|
|
85952ce6b7 | ||
|
|
bf9ce68d8b | ||
|
|
08c5992447 | ||
|
|
dfc7f7c827 | ||
|
|
efdbbc6098 | ||
|
|
185cf90d4c | ||
|
|
4db4790270 | ||
|
|
be3b890e2f | ||
|
|
4536f96493 | ||
|
|
a598c3e7a8 | ||
|
|
d9f5ee9d76 | ||
|
|
a4ced609cd | ||
|
|
673a4e6805 | ||
|
|
d017ccfbd4 | ||
|
|
1f52ed2e83 | ||
|
|
08e83f616c | ||
|
|
51edc4652e | ||
|
|
a3c6f38642 | ||
|
|
a1db53f50b | ||
|
|
9e1046fde3 | ||
|
|
17173f72e0 | ||
|
|
f60a99c357 | ||
|
|
1d763f1bc9 | ||
|
|
248b94c296 | ||
|
|
f52447ff58 | ||
|
|
0cbacbb959 | ||
|
|
a01edecaef | ||
|
|
779756f1ab | ||
|
|
723fedc066 | ||
|
|
a83bb23540 | ||
|
|
5d68a5133e | ||
|
|
8ca629151d | ||
|
|
693965af28 | ||
|
|
e645a350f2 | ||
|
|
85e9808550 | ||
|
|
0ce1c4565e | ||
|
|
478964ad30 | ||
|
|
74a04e3b35 | ||
|
|
a48992ed9d | ||
|
|
9a6ea8c9bb | ||
|
|
51b05cb128 | ||
|
|
de33d6d44c | ||
|
|
3d5cc98df5 | ||
|
|
13f3b54393 | ||
|
|
f17f7b2272 | ||
|
|
f61dc7197a | ||
|
|
0534508bc3 | ||
|
|
446c7ffd6a | ||
|
|
79e6216669 | ||
|
|
5047e48de5 | ||
|
|
bd48112bf9 | ||
|
|
5dc100d900 | ||
|
|
9f2ecb67d4 | ||
|
|
5e4f45826e | ||
|
|
be6ff21184 | ||
|
|
5c660fbe7f | ||
|
|
108718f275 | ||
|
|
ab53a0b403 | ||
|
|
49b815bc98 | ||
|
|
c702814203 | ||
|
|
0c0172a0b6 | ||
|
|
a8266c22f6 | ||
|
|
532c7fbc8f | ||
|
|
23ed381859 | ||
|
|
1ad11b0c58 | ||
|
|
18cca916a0 | ||
|
|
97012082de | ||
|
|
423810cf61 | ||
|
|
a5159ce8e1 | ||
|
|
4dd3952c19 | ||
|
|
1e26b5c5f1 | ||
|
|
67897dfcc0 | ||
|
|
0100604798 | ||
|
|
47afe01721 | ||
|
|
a2e12b795f | ||
|
|
806ab3438e | ||
|
|
f4be90fdd0 | ||
|
|
dd46767ee3 | ||
|
|
a2c712e5b3 | ||
|
|
35f3a0077a | ||
|
|
bc4195942a | ||
|
|
03baca2ed7 | ||
|
|
54a9c31a1a | ||
|
|
db5073223d | ||
|
|
afd766999c | ||
|
|
0637490216 | ||
|
|
6a3ba87b22 | ||
|
|
20b287da52 | ||
|
|
18a378976b | ||
|
|
8e7af49206 | ||
|
|
edeab082d4 | ||
|
|
7b76baaacf | ||
|
|
053365cb67 | ||
|
|
8301120a95 | ||
|
|
f15f0a6226 | ||
|
|
0cfcadf5fa | ||
|
|
435c4acba6 | ||
|
|
edb913855d | ||
|
|
24739e1638 | ||
|
|
54b906addb | ||
|
|
4a7a8df8a4 | ||
|
|
f1dd62c936 | ||
|
|
80cc7b0d64 | ||
|
|
eb4fbf3c0b | ||
|
|
c1cf1206fc | ||
|
|
efebc02d24 | ||
|
|
21dca8c17f | ||
|
|
4eb9839f77 | ||
|
|
3b7906ea04 | ||
|
|
9d17858500 | ||
|
|
d5ceb5f465 | ||
|
|
7dd2a0bbb4 | ||
|
|
13284fb3b9 | ||
|
|
f42c5ec0ce | ||
|
|
6b269839cb | ||
|
|
2eb3e0a278 | ||
|
|
183a437678 | ||
|
|
116b8171f8 | ||
|
|
c8c723bf4a | ||
|
|
d01cf018ce | ||
|
|
c701ab0776 | ||
|
|
180269d6b0 | ||
|
|
645c604fd4 | ||
|
|
de210db90d | ||
|
|
beddf1c772 | ||
|
|
75e618ee4a | ||
|
|
d2a3ba182b | ||
|
|
427f78b14d | ||
|
|
febcf237ca | ||
|
|
5e158c3bd7 | ||
|
|
b4c9c86ba6 | ||
|
|
7c00853f5d | ||
|
|
a0fcb116f5 | ||
|
|
e46b33544d | ||
|
|
6b9c3ad4e7 | ||
|
|
dc12b9a197 | ||
|
|
d473f56c3a | ||
|
|
4138ab3d7d | ||
|
|
e18d1a451d | ||
|
|
a3048cd393 | ||
|
|
dd8fdc6c0a | ||
|
|
9099e4b709 | ||
|
|
52b176b9eb | ||
|
|
69fd70787c | ||
|
|
ff37aea9c8 | ||
|
|
85f73977bf | ||
|
|
2c04ed48c2 | ||
|
|
1228754280 | ||
|
|
a43ee054ad | ||
|
|
83bc714739 | ||
|
|
a08390c84a | ||
|
|
8b6eacecfe | ||
|
|
fb96787697 | ||
|
|
9cff77be62 | ||
|
|
0d1643da66 | ||
|
|
5e7027647a | ||
|
|
28f6f09e8f | ||
|
|
332af5d21b | ||
|
|
e187005130 | ||
|
|
0357386f7c | ||
|
|
47f8e5b8c6 | ||
|
|
e95c9d73a1 | ||
|
|
b7174070fe | ||
|
|
dd06a7b62c | ||
|
|
ff9d480b6e | ||
|
|
229ad9108b | ||
|
|
0e332d291a | ||
|
|
180904cdc2 | ||
|
|
0e83f7d807 | ||
|
|
5d7931fcaf | ||
|
|
2e906b0bf5 | ||
|
|
33ae6f12de | ||
|
|
f302c2e154 | ||
|
|
3ee2492382 | ||
|
|
4caed50018 | ||
|
|
aadb19a792 | ||
|
|
9f8211a873 | ||
|
|
d45fc05e5d | ||
|
|
955a3a054e | ||
|
|
60f265a5fa | ||
|
|
a2d82a1a7b | ||
|
|
0875d728e8 | ||
|
|
f3cf6b8b38 | ||
|
|
e4465cffb0 | ||
|
|
ca35d714dc | ||
|
|
c06e7348c4 | ||
|
|
60ac8a6ebd | ||
|
|
e3450baeb3 | ||
|
|
72661623f3 | ||
|
|
b4d97d9432 | ||
|
|
b40100f78b | ||
|
|
a343d2b42c | ||
|
|
d3d7e54cff | ||
|
|
6535bc3d5e | ||
|
|
f966fc8d84 | ||
|
|
8a20bbd943 | ||
|
|
cd0f6d85ba | ||
|
|
d51edbb3bb | ||
|
|
553e475cfb | ||
|
|
b9367446d9 | ||
|
|
82d9fccec8 | ||
|
|
cbbcfb7a3a | ||
|
|
1f862b27c1 | ||
|
|
883b03349e | ||
|
|
f740a6ba61 | ||
|
|
fb3e761a37 | ||
|
|
3c7411328d | ||
|
|
9c2bfdfead | ||
|
|
4f3bd1ff4a | ||
|
|
69d10489b8 | ||
|
|
df031b2222 | ||
|
|
850b9e5e3d | ||
|
|
a95a208e1b | ||
|
|
50ff3628f7 | ||
|
|
14d203055b | ||
|
|
4628e28592 | ||
|
|
7fb3d13733 | ||
|
|
11ff81f852 | ||
|
|
0f5af4b990 | ||
|
|
85420602e8 | ||
|
|
6ccf55b601 | ||
|
|
42c9e21d04 | ||
|
|
3030c300f2 | ||
|
|
48b969f3c3 | ||
|
|
bbb78aa5e6 | ||
|
|
31380bbef2 | ||
|
|
479a7d9162 | ||
|
|
6fe02f156a | ||
|
|
c4ed210fed | ||
|
|
ae686fab38 | ||
|
|
8edca9ed5d | ||
|
|
05bafd0db5 | ||
|
|
341d699240 | ||
|
|
552093d962 | ||
|
|
eb6063cc2d | ||
|
|
550ff4ff18 | ||
|
|
5383a8b77c | ||
|
|
86117091fe | ||
|
|
b113028a5f | ||
|
|
60a3f21857 | ||
|
|
65a2ea3935 | ||
|
|
6ecddfc6c0 | ||
|
|
d65d48db48 | ||
|
|
f509b26800 | ||
|
|
43fb6fe6e5 | ||
|
|
9d2d8684b6 | ||
|
|
1689925508 | ||
|
|
4d249553bf | ||
|
|
43ea1044cd | ||
|
|
cc4a301dc1 | ||
|
|
ab67eea36e | ||
|
|
fa326eba6f | ||
|
|
c30ebdf287 | ||
|
|
835bcb7207 | ||
|
|
777424ad18 | ||
|
|
4985e7e96d | ||
|
|
ca1e64ec10 | ||
|
|
26029508c6 | ||
|
|
118259a96b | ||
|
|
35e8dcf2bc | ||
|
|
359a5d01e6 | ||
|
|
1c2acbb57f | ||
|
|
01a702c529 | ||
|
|
1ee584c5a1 | ||
|
|
fc10bd7749 | ||
|
|
f2568092a7 | ||
|
|
6b5d5a6334 | ||
|
|
195ed57025 | ||
|
|
008b4a134b | ||
|
|
1b9bfb5b62 | ||
|
|
edeaa1333b | ||
|
|
e678b52a7e | ||
|
|
b549db58e4 | ||
|
|
c14059f66a | ||
|
|
11f69daaec | ||
|
|
c0120c0f17 | ||
|
|
c1a5f9adf1 | ||
|
|
5087f27546 | ||
|
|
efbff9e217 | ||
|
|
20ea83ae93 | ||
|
|
05daeb561c | ||
|
|
bfff001752 | ||
|
|
c3a45a1584 | ||
|
|
b09a92a264 | ||
|
|
44a792583c | ||
|
|
71c8267dea | ||
|
|
b6688f56b5 | ||
|
|
f703164098 | ||
|
|
6a6b27e905 | ||
|
|
731a46c612 | ||
|
|
92a8078322 | ||
|
|
ba2d77f0bb | ||
|
|
3d21c15281 | ||
|
|
cb4b20c057 | ||
|
|
2af2767699 | ||
|
|
e4bb19b98a | ||
|
|
7e784c9509 | ||
|
|
3dd27797dc | ||
|
|
5e059272dc | ||
|
|
0a9aeca3bc | ||
|
|
11d42e0f93 | ||
|
|
85d8658037 | ||
|
|
dfa29950ef | ||
|
|
b7366a8704 | ||
|
|
57416103c3 | ||
|
|
72bd3731de | ||
|
|
9fab20ca6c | ||
|
|
8b4453f32d | ||
|
|
f4b77e6b03 | ||
|
|
c3da2fca9b | ||
|
|
c0d68c5740 | ||
|
|
5398564aec | ||
|
|
904dc80aab | ||
|
|
516de20148 | ||
|
|
be088709af | ||
|
|
fd4f5057b3 | ||
|
|
686d5e8b03 | ||
|
|
c371ff5504 | ||
|
|
9862dca4aa | ||
|
|
716321b37b | ||
|
|
b3ed8bad9c | ||
|
|
0a170f5c29 | ||
|
|
ec0fba7913 | ||
|
|
2630c2baf1 | ||
|
|
a01865b19b | ||
|
|
00f6115a93 | ||
|
|
a466202bac | ||
|
|
bb12ef24f8 | ||
|
|
c862c6de0f | ||
|
|
a1cb3ec8d5 | ||
|
|
187d4cd02d | ||
|
|
20a0f9b026 | ||
|
|
f9c0ed6ad4 | ||
|
|
27652e7191 | ||
|
|
828665cb29 | ||
|
|
fa784c83bf | ||
|
|
2d83176892 | ||
|
|
776758c7e8 | ||
|
|
d72afe9b92 | ||
|
|
dee61b5499 | ||
|
|
9f73d0a7fb | ||
|
|
bc804c9e56 | ||
|
|
35f450aee7 | ||
|
|
5803b4ca27 | ||
|
|
7bccd62a4f | ||
|
|
335838f2b2 | ||
|
|
204d8cc7eb | ||
|
|
61f5d4b172 | ||
|
|
3d829c6ce8 | ||
|
|
5d9852b72c | ||
|
|
f561ece9d1 | ||
|
|
66eabd3bd6 | ||
|
|
b2f92acbf6 | ||
|
|
6f30ecb365 | ||
|
|
32a89d3895 | ||
|
|
97bf958b74 | ||
|
|
30f8afca85 | ||
|
|
ed88a8e3e3 | ||
|
|
421f690f42 | ||
|
|
a330e8afb2 | ||
|
|
d8e5c9f033 | ||
|
|
209646e012 | ||
|
|
7d518df13c | ||
|
|
ca603f41db | ||
|
|
7bb18f6fad | ||
|
|
1a0e2031d2 | ||
|
|
4f83d69205 | ||
|
|
cfafd90f15 | ||
|
|
a94f416b3c | ||
|
|
fd47e2de29 | ||
|
|
abbc403f73 | ||
|
|
b41c536865 | ||
|
|
bee7314dd7 | ||
|
|
d25407e3b4 | ||
|
|
ad697369ef | ||
|
|
edbdb17a2f | ||
|
|
9d2e2a1ea2 | ||
|
|
6df0597c5e | ||
|
|
093eb28463 | ||
|
|
7d0c279f5b | ||
|
|
d98a6a09bb | ||
|
|
02cf7b9d66 | ||
|
|
9253b783dd | ||
|
|
2ed82be809 | ||
|
|
1c1499dec8 | ||
|
|
f7f151d2a9 | ||
|
|
13f29ee3ce | ||
|
|
ce68f52ca0 | ||
|
|
33172767a6 | ||
|
|
649b3839d2 | ||
|
|
666fb4c194 | ||
|
|
9301497a4a | ||
|
|
6956e21caf | ||
|
|
71dec5746e | ||
|
|
0ea8f4c259 | ||
|
|
8602814dc3 | ||
|
|
20e60edbc6 | ||
|
|
88f59ad1eb | ||
|
|
668a899260 | ||
|
|
75ae85a5d4 | ||
|
|
abc1b4e1b2 | ||
|
|
fa194f0cef | ||
|
|
b3fbd89456 | ||
|
|
5334a4cbe0 | ||
|
|
8f2adf0a50 | ||
|
|
62dfd7cef0 | ||
|
|
a8321e8cd3 | ||
|
|
0119552336 | ||
|
|
033abc64c8 | ||
|
|
ef8014bc6d | ||
|
|
96a880b5ae | ||
|
|
bfedcde978 | ||
|
|
badad70984 | ||
|
|
7611188535 | ||
|
|
31f2cc1fdc | ||
|
|
187e646fa0 | ||
|
|
b2721db8e0 | ||
|
|
fd9f521c60 | ||
|
|
edd6fbe35f | ||
|
|
839c9c9884 | ||
|
|
3a1fe992d6 | ||
|
|
9899f6d1f8 | ||
|
|
446a464b3d | ||
|
|
6a347799c7 | ||
|
|
2dae89e41c | ||
|
|
e8119ba80d | ||
|
|
a5ecad8fae | ||
|
|
1708a4c831 | ||
|
|
a237078b68 | ||
|
|
4ef63d026e | ||
|
|
b8ae3cdd3f | ||
|
|
46d855ce0f | ||
|
|
a3306bbb5a | ||
|
|
1428a5e7e2 | ||
|
|
427940b3be | ||
|
|
7a3e7dc631 | ||
|
|
b38bb40a5d | ||
|
|
b2e1e2e89a | ||
|
|
02fcc42395 | ||
|
|
3accc406a7 | ||
|
|
1c238b7ce4 | ||
|
|
45770173c4 | ||
|
|
3e5f6abdad | ||
|
|
4117c6127e | ||
|
|
aae1fad7ab | ||
|
|
ada65b5ce2 | ||
|
|
14c0c65e17 | ||
|
|
0201aa9bd1 | ||
|
|
dca530f2f2 | ||
|
|
c9f9668e52 | ||
|
|
4f636b7cfb | ||
|
|
34a04c0059 | ||
|
|
00ee58d3fd | ||
|
|
ecb3c4f4f3 | ||
|
|
9dace592c0 | ||
|
|
5d73221b06 | ||
|
|
d50958c9ee | ||
|
|
52bb005792 | ||
|
|
3121aa7164 | ||
|
|
87c54f07c6 | ||
|
|
f1d4a686b1 | ||
|
|
56ac037128 | ||
|
|
e977045d5f | ||
|
|
3301b106ab | ||
|
|
e645f55191 | ||
|
|
278d25c803 | ||
|
|
ac14154b5d | ||
|
|
3352e743f7 | ||
|
|
79d8c17aaa | ||
|
|
ef7ce21ff3 | ||
|
|
a8bcc6206f | ||
|
|
ddfeafc5e2 | ||
|
|
85cdd40102 | ||
|
|
d412d8536c | ||
|
|
bf1a314076 | ||
|
|
e2b2ff7f6f | ||
|
|
a589c9aa69 | ||
|
|
d5b05e391a | ||
|
|
dc7a20280f | ||
|
|
d36fc45c99 | ||
|
|
990d92e569 | ||
|
|
7d4ef4f9a1 | ||
|
|
7baabcef96 | ||
|
|
ded15ecc3f | ||
|
|
0ad3ec444c | ||
|
|
7939503a11 | ||
|
|
8564f93706 | ||
|
|
f3e550d003 | ||
|
|
6c525b5dcd | ||
|
|
bb10d25561 | ||
|
|
7ec5adb6b4 | ||
|
|
ffb73d61fc | ||
|
|
3ee6c34d08 | ||
|
|
2c26ccbc72 | ||
|
|
cfbde151fa | ||
|
|
e278978ad9 | ||
|
|
a284e0c2f7 | ||
|
|
558c920181 | ||
|
|
7622fe9fc5 | ||
|
|
b32aec682c | ||
|
|
d54d25a432 | ||
|
|
ba19bdb90a | ||
|
|
58d10fac84 | ||
|
|
eecc1def2a | ||
|
|
f75fbc3744 | ||
|
|
07750c1f8c | ||
|
|
9ae0d9b0a1 | ||
|
|
c9f5828eb9 | ||
|
|
35a6a1883c | ||
|
|
080c48327e | ||
|
|
28506538a3 | ||
|
|
d578dedd0c | ||
|
|
c7aa105517 | ||
|
|
3c140c3e4d | ||
|
|
8d94b67aaa | ||
|
|
887cca109f | ||
|
|
239061b688 | ||
|
|
6d067428e0 | ||
|
|
b11f13181e | ||
|
|
e52b8e9a13 | ||
|
|
aa567ab078 | ||
|
|
50daf49cf0 | ||
|
|
a49fb65fac | ||
|
|
adfd1e614d | ||
|
|
a3eef04342 | ||
|
|
cf5e660951 | ||
|
|
671d6acfff | ||
|
|
125e759120 | ||
|
|
e81832e48f | ||
|
|
0b17da3b87 | ||
|
|
8379902adb | ||
|
|
00c4ffc154 | ||
|
|
3473337e7d | ||
|
|
4493178693 | ||
|
|
40452dcefe | ||
|
|
082afadb5b | ||
|
|
9ca61f9ef5 | ||
|
|
28a628ec93 | ||
|
|
12b5e21314 | ||
|
|
95aaccb35e | ||
|
|
ac053b00e8 | ||
|
|
938c7df28a | ||
|
|
6e22ea178b | ||
|
|
253f336509 | ||
|
|
3a7e0da80b | ||
|
|
073860cd5b | ||
|
|
18be4db320 | ||
|
|
5cbcbe6d7e | ||
|
|
1ef3f83e46 | ||
|
|
6ab0a839b1 | ||
|
|
e329753939 | ||
|
|
843751b53f | ||
|
|
1f083a52eb | ||
|
|
879eb6ee9f | ||
|
|
2db1e6b596 | ||
|
|
94f5ba7d1a | ||
|
|
e7458f3032 | ||
|
|
840cee206a | ||
|
|
511cdbbfe2 | ||
|
|
35f1999b3a | ||
|
|
3f55c694b8 | ||
|
|
6df0147fe9 | ||
|
|
5e3b4b126e | ||
|
|
b564fe8a0d | ||
|
|
1dc3a7202a | ||
|
|
cfa01d3c15 | ||
|
|
c4cac468ff | ||
|
|
a034bf9710 | ||
|
|
0336b0a15c | ||
|
|
94a2cfe7fc | ||
|
|
d22d0fdab5 | ||
|
|
6f9f47bfe3 | ||
|
|
b2402cdd39 | ||
|
|
289e1ee315 | ||
|
|
c1d1cbda70 | ||
|
|
17bac3714d | ||
|
|
9699fb8894 | ||
|
|
16809c0136 | ||
|
|
e0408510b8 | ||
|
|
14782c184f | ||
|
|
527f5c5ae6 | ||
|
|
b9aa4f1482 | ||
|
|
5ea6234cfb | ||
|
|
d056e1de1e | ||
|
|
2feb0246ff | ||
|
|
f4be045f08 | ||
|
|
a42ca225e3 | ||
|
|
5fb1bed9d2 | ||
|
|
c0c903d81a | ||
|
|
60b56d61ed | ||
|
|
fe1f334e2e | ||
|
|
fe4d70a9f9 | ||
|
|
93fded58f0 | ||
|
|
9a7b8ca27d | ||
|
|
aa7d75fae4 | ||
|
|
be345ffcc1 | ||
|
|
b3589312f8 | ||
|
|
08bd45d07e | ||
|
|
9af60c4192 | ||
|
|
6c48a94ab3 | ||
|
|
2897be7a10 | ||
|
|
69c0b04be6 | ||
|
|
837e309781 | ||
|
|
dca369ba30 | ||
|
|
b49d66aa68 | ||
|
|
4ce8c82244 | ||
|
|
ab9a530403 | ||
|
|
f9d91178b7 | ||
|
|
d0b8232a36 | ||
|
|
8f21e2368f | ||
|
|
87ec1a9fc5 | ||
|
|
cb1dcab37d | ||
|
|
91980277e1 | ||
|
|
c18b259b27 | ||
|
|
dffc82781b | ||
|
|
aef77965e7 | ||
|
|
f21da0cc2b | ||
|
|
234e0ee764 | ||
|
|
4262bb801e | ||
|
|
093941f8ba | ||
|
|
1cb1c35e2a | ||
|
|
432535e238 | ||
|
|
b40dc9d96d | ||
|
|
cb12e1208b | ||
|
|
b8225bd206 | ||
|
|
880c22eef9 | ||
|
|
b379c8380d | ||
|
|
6a61a113b0 | ||
|
|
4373eae1fe | ||
|
|
d12e4305bd | ||
|
|
7c8a45fd4c | ||
|
|
c28f8f763a | ||
|
|
096de6cddf | ||
|
|
ad52476159 | ||
|
|
e3d11ab681 | ||
|
|
162f37e00f | ||
|
|
d879634810 | ||
|
|
4634f853f1 | ||
|
|
ae861f080b | ||
|
|
d058721243 | ||
|
|
9fdef5eb5d | ||
|
|
b4488bf1e7 | ||
|
|
fa6d6b5438 | ||
|
|
02f53a55cc | ||
|
|
fdf0b6263a | ||
|
|
59fa5112fc | ||
|
|
a8033248ae | ||
|
|
9a6f299b41 | ||
|
|
2f1ee93e86 | ||
|
|
34fa5d6bfc | ||
|
|
357f728043 | ||
|
|
9522ee93dc | ||
|
|
c68b6116a2 | ||
|
|
f0db879c9c | ||
|
|
07d8a3d765 | ||
|
|
e35e264d81 | ||
|
|
d537e6a869 | ||
|
|
d4dd1861a9 | ||
|
|
3019a31fbb | ||
|
|
303b9912ff | ||
|
|
0259b2e5b9 | ||
|
|
5c7e8029f4 | ||
|
|
08e3fd3141 | ||
|
|
30123fd6ff | ||
|
|
3955299983 | ||
|
|
b5d0df3ca7 | ||
|
|
22c65da9d1 | ||
|
|
578c1ecfaf | ||
|
|
d8d00a7e26 | ||
|
|
37f0f7a138 | ||
|
|
f61e9367ec | ||
|
|
3c3e59e932 | ||
|
|
29e22a0c6c | ||
|
|
0d1f424425 | ||
|
|
1c01e23867 | ||
|
|
f763a8694b | ||
|
|
675b853b29 | ||
|
|
2434bf14d5 | ||
|
|
70fbbfe2a0 | ||
|
|
e096898a05 | ||
|
|
3fbccf3f64 | ||
|
|
36585395f1 | ||
|
|
e4b0a1613f | ||
|
|
1192e474c5 | ||
|
|
e48ea99e48 | ||
|
|
072f2a0ee9 | ||
|
|
aecb536a34 | ||
|
|
a68686cb06 | ||
|
|
ba8cf3e01e | ||
|
|
b0c5189c4b | ||
|
|
d44eb67dec | ||
|
|
58d36b08e2 | ||
|
|
98906731e3 | ||
|
|
035a4b0928 | ||
|
|
85fbe666ea | ||
|
|
741d0bc686 | ||
|
|
ded539ce7a | ||
|
|
c53fd25d1c | ||
|
|
da32621c55 | ||
|
|
4ccf33af03 | ||
|
|
a5af7a70f3 | ||
|
|
16ab0d29d6 | ||
|
|
05ad9022c0 | ||
|
|
fef211b220 | ||
|
|
6aee1ee41f | ||
|
|
bab7f9b1f3 | ||
|
|
340e7afd06 | ||
|
|
cb83c9cff2 | ||
|
|
911a8fed06 | ||
|
|
eb8b43fe36 | ||
|
|
2a15dc57d8 | ||
|
|
67678e35bb | ||
|
|
2f00db8081 | ||
|
|
38fc826053 | ||
|
|
300578a44b | ||
|
|
dc2bcdcfbc | ||
|
|
7e18e89012 | ||
|
|
24f47722c0 | ||
|
|
04b679a4a7 | ||
|
|
f6713008aa | ||
|
|
15dc62855b | ||
|
|
4ed3df2b08 | ||
|
|
8a3eaae29c | ||
|
|
22edc016dd | ||
|
|
5205daae6d | ||
|
|
7ea79ebe56 | ||
|
|
3bfa8bd81e | ||
|
|
39abf63698 | ||
|
|
f68a6d1119 | ||
|
|
1a1a02d080 | ||
|
|
dacffc5f90 | ||
|
|
f2068b2663 | ||
|
|
989282ffbe | ||
|
|
e469b2e6ad | ||
|
|
8eaada992f | ||
|
|
f5dba45fa0 | ||
|
|
e72b5893c4 | ||
|
|
e78a176e9f | ||
|
|
8143999803 | ||
|
|
219c2c94e8 | ||
|
|
37f612801f | ||
|
|
0b12b7aa89 | ||
|
|
14da25bd9e | ||
|
|
3a713541a2 | ||
|
|
c7a547a875 | ||
|
|
e12caf186c | ||
|
|
1ee6e31538 | ||
|
|
083c94403b | ||
|
|
67121decbf | ||
|
|
fcd6bb1084 | ||
|
|
a81a4b895a | ||
|
|
c50c5177b8 | ||
|
|
30eefe57ef | ||
|
|
ce33cce5a9 | ||
|
|
d0dfde382c | ||
|
|
7fb2d0526e | ||
|
|
fb34467cba | ||
|
|
7e62cddb97 | ||
|
|
78b31149b5 | ||
|
|
817038563f | ||
|
|
56ca2305bd | ||
|
|
fc7bafe3d9 | ||
|
|
d622f38e1d | ||
|
|
139810c8a5 | ||
|
|
f8cc332ed7 | ||
|
|
db24bd4d78 | ||
|
|
d056013296 | ||
|
|
7e647f7085 | ||
|
|
322068b5e0 | ||
|
|
96247d5fa0 | ||
|
|
6b7338aff0 | ||
|
|
59d85cc218 | ||
|
|
7f90fdedf1 | ||
|
|
7723c956bc | ||
|
|
d0c10a8f72 | ||
|
|
c56dd52bd6 | ||
|
|
a7374f5bbd | ||
|
|
251d62f3c4 | ||
|
|
b8c041d0d6 | ||
|
|
dd42037f21 | ||
|
|
50575d45c1 | ||
|
|
7268c7fb70 | ||
|
|
83572960d5 | ||
|
|
39f22fa314 | ||
|
|
69ab5d8c2e | ||
|
|
58111465bc | ||
|
|
697e56962a | ||
|
|
7d6c45f689 | ||
|
|
faa34c9230 | ||
|
|
8a64c1815a | ||
|
|
f65f166ea6 | ||
|
|
f054e700a2 | ||
|
|
ff8b9e4e1a | ||
|
|
ed47e94a70 | ||
|
|
93090f3481 | ||
|
|
fa211574a2 | ||
|
|
9a18eda404 | ||
|
|
fd3e941472 | ||
|
|
ad03980c2b | ||
|
|
a6af7a90cb | ||
|
|
ba170632a5 | ||
|
|
f8c536afd3 | ||
|
|
53b75e1ca2 | ||
|
|
a632b08664 | ||
|
|
954b7f6d9e | ||
|
|
8c0fb90420 | ||
|
|
5d697a3189 | ||
|
|
2c04a4daec | ||
|
|
f3c1296105 | ||
|
|
50c3f025e2 | ||
|
|
9b4a3bcbef | ||
|
|
d8486e8f90 | ||
|
|
fc731c3f58 | ||
|
|
a62fbd54d4 | ||
|
|
f81a7a397a | ||
|
|
8543cb7ece | ||
|
|
5015c9d8f3 | ||
|
|
2b4dede658 | ||
|
|
d2b15ae679 | ||
|
|
5ece8fd2f7 | ||
|
|
128203800c | ||
|
|
f0a1397eea | ||
|
|
ef42055de1 | ||
|
|
15aff6030c | ||
|
|
215a28fac5 | ||
|
|
e9e155201f | ||
|
|
21a457cadd | ||
|
|
8e7eab636f | ||
|
|
d7ce46c14a | ||
|
|
ee7f8940d0 | ||
|
|
cf1883a039 | ||
|
|
7ec614a691 | ||
|
|
e4fc49769f | ||
|
|
d97df9cddd | ||
|
|
33a254ce92 | ||
|
|
3ec0366c21 | ||
|
|
759db2d20e | ||
|
|
8f7c6521a9 | ||
|
|
725a7f21c4 | ||
|
|
e24611fde9 | ||
|
|
7a077095ee | ||
|
|
fade09ca8f | ||
|
|
9ab39904e8 | ||
|
|
fb5fa57fd6 | ||
|
|
9e84e78215 | ||
|
|
f5bf2ac4ca | ||
|
|
c50a8e7740 | ||
|
|
3ece911018 | ||
|
|
1011b67f0a | ||
|
|
497679284a | ||
|
|
263df3ac4d | ||
|
|
c751a180a4 | ||
|
|
3ee6a0cf6f | ||
|
|
0c23f36e36 | ||
|
|
40b84fd676 | ||
|
|
e5e1d3b8e5 | ||
|
|
9bba225157 | ||
|
|
196c615f53 | ||
|
|
353dce789d | ||
|
|
f1be7ed69d | ||
|
|
37146c1e10 | ||
|
|
feba94547a | ||
|
|
1b82b64a0a | ||
|
|
0f8cd31e0a | ||
|
|
c351a5cf72 | ||
|
|
98a58779ad | ||
|
|
1aef721794 | ||
|
|
7373d958a5 | ||
|
|
37fdbf25ff | ||
|
|
1580709c97 | ||
|
|
c7f1f67ee9 | ||
|
|
8d90c9e03a | ||
|
|
40818ae853 | ||
|
|
364ea9ca29 | ||
|
|
f6b1bd9fe8 | ||
|
|
30c7319811 | ||
|
|
41fbf362fa | ||
|
|
e8867d0fbc | ||
|
|
3bf8aad127 | ||
|
|
fb5354c3cd | ||
|
|
a62105fa28 | ||
|
|
65592dc42d | ||
|
|
3a345c0d7f | ||
|
|
3da11e615f | ||
|
|
3eb87a878a | ||
|
|
91ed869dba | ||
|
|
bd5d0093ef | ||
|
|
bd7ba09f10 | ||
|
|
851b6a837f | ||
|
|
d8064d1567 | ||
|
|
046edd5a86 | ||
|
|
8d8eb5d13b | ||
|
|
2a3adb135b | ||
|
|
b0c4c62668 | ||
|
|
a08cb3b8e4 | ||
|
|
943d61dee9 | ||
|
|
d22427f578 | ||
|
|
e4167380b9 | ||
|
|
445afcc50c | ||
|
|
e0e37d9a2d | ||
|
|
d94faae5af | ||
|
|
e7f38abd77 | ||
|
|
01585877d7 | ||
|
|
8baa800e30 | ||
|
|
84b2c24f9f | ||
|
|
3fc8ccf8be | ||
|
|
b294f1a854 | ||
|
|
06725441a1 | ||
|
|
aa40a27558 | ||
|
|
f5958a7ff2 | ||
|
|
f3221e6e76 | ||
|
|
7649fa11d3 | ||
|
|
98aa70c9ce | ||
|
|
a3be5c9616 | ||
|
|
decc8b9141 | ||
|
|
1c7df4d9f7 | ||
|
|
b94f307379 | ||
|
|
33d9e35667 | ||
|
|
ad9a3e01de | ||
|
|
2cc6d03a8b | ||
|
|
6785979fbc | ||
|
|
23958b3d03 | ||
|
|
831e31ea9d | ||
|
|
66483b6ae8 | ||
|
|
4614d04be4 | ||
|
|
1285e9aa69 | ||
|
|
d108cec685 | ||
|
|
764b9dda7e | ||
|
|
82d289cfcf | ||
|
|
184c91cfbc | ||
|
|
10103b58f0 | ||
|
|
2678100149 | ||
|
|
09a9dfe591 | ||
|
|
af3e8d5515 | ||
|
|
1b72eca5ec | ||
|
|
df5968660b | ||
|
|
eb04e1dcee | ||
|
|
7dff5001b0 | ||
|
|
ca93673c10 | ||
|
|
71a4664d1f | ||
|
|
429f30fca7 | ||
|
|
5376ce4bdb | ||
|
|
96b57994d9 | ||
|
|
d1971cdcae | ||
|
|
65116563fd | ||
|
|
d811e42095 | ||
|
|
2a7e185d2e | ||
|
|
1a894d71b8 | ||
|
|
9213a40219 | ||
|
|
bf8a6ebbf8 | ||
|
|
2bcb0b0ac1 | ||
|
|
9767243a6d | ||
|
|
df7fbe5a66 | ||
|
|
c16dd0c9b6 | ||
|
|
f5c47424f3 | ||
|
|
6207662ca5 | ||
|
|
d63cc80507 | ||
|
|
b857157c7b | ||
|
|
2b8d12f987 | ||
|
|
28682c7c33 | ||
|
|
fe61e4f3e2 | ||
|
|
7916e81745 | ||
|
|
4e6fb7799a | ||
|
|
03dd0e530e | ||
|
|
cb6f6247fd | ||
|
|
c33fc7630e | ||
|
|
2910160af9 | ||
|
|
3b2247de39 | ||
|
|
60212dcbcc | ||
|
|
1b8b12cbc3 | ||
|
|
e57ab7f030 | ||
|
|
2f13fa79ba | ||
|
|
c616c8ce29 | ||
|
|
0f2b56adb4 | ||
|
|
a2ba0f8b9f | ||
|
|
c6a7b52e34 | ||
|
|
64b67e5396 | ||
|
|
ab2084692d | ||
|
|
03133dc1fd | ||
|
|
7e1e259897 | ||
|
|
6720c0e993 | ||
|
|
53bb2b2945 | ||
|
|
a2c5ce5ebc | ||
|
|
b4928f662a | ||
|
|
b9b509ad9b | ||
|
|
d93ad8044a | ||
|
|
9d14e8113f | ||
|
|
84d1d758c1 | ||
|
|
cbfd722c92 | ||
|
|
be6496e569 | ||
|
|
de086a2b07 | ||
|
|
3f8df0f036 | ||
|
|
b2c49aa786 | ||
|
|
a0e7bd3996 | ||
|
|
e06be9ee25 | ||
|
|
07473f854e | ||
|
|
f342e46f53 | ||
|
|
d3a287dcdf | ||
|
|
ce2101a8e1 | ||
|
|
2d456a6dc4 | ||
|
|
a3e0e14cef | ||
|
|
bbade75061 | ||
|
|
645e82fb04 | ||
|
|
3245b05c5f | ||
|
|
61ef81832d | ||
|
|
7dea6fc1b7 | ||
|
|
bd306e9400 | ||
|
|
3e686211e1 | ||
|
|
6d1b4b0a39 | ||
|
|
58938fc07c | ||
|
|
96dd4e02f3 | ||
|
|
411c537438 | ||
|
|
bbd112280a | ||
|
|
28d074366e | ||
|
|
11d76656de | ||
|
|
1c96bc31d5 | ||
|
|
0030064f55 | ||
|
|
4726f5c136 | ||
|
|
c7fafedc51 | ||
|
|
3eeb70ae36 | ||
|
|
29b1a3dca3 | ||
|
|
caf844b5fb | ||
|
|
6b7bdf8c4f | ||
|
|
aad433a3bc | ||
|
|
3f1bb56826 | ||
|
|
b2b3add616 | ||
|
|
2d484d4a8e | ||
|
|
2f252f19c9 | ||
|
|
a27f372785 | ||
|
|
f074e642ec | ||
|
|
217ed905d4 | ||
|
|
b920efc955 | ||
|
|
330fadbea9 | ||
|
|
50c595e3d6 | ||
|
|
26f258c6cf | ||
|
|
f15a72e59d | ||
|
|
8accaae6b1 | ||
|
|
d4259501af | ||
|
|
fd5d5ae98e | ||
|
|
457901ff82 | ||
|
|
e201be1c65 | ||
|
|
acde14372d | ||
|
|
79988a2325 | ||
|
|
784f6e703c | ||
|
|
29b157f287 | ||
|
|
c030bd35ca | ||
|
|
06fe076ce2 | ||
|
|
ae6cba067c | ||
|
|
72ae19a95d | ||
|
|
1f889be07a | ||
|
|
39061b659a | ||
|
|
d38f29ac7c | ||
|
|
1a8e67f4de | ||
|
|
8265c302ad | ||
|
|
110d7c6acf | ||
|
|
244b767f8f | ||
|
|
f40950efc9 | ||
|
|
0e0534c273 | ||
|
|
9b3ea3656f | ||
|
|
62b2a367ff | ||
|
|
ab9dd32902 | ||
|
|
43fc498297 | ||
|
|
ef3eee7873 | ||
|
|
9f0deea9dd | ||
|
|
e3798600ed | ||
|
|
00834cd5e0 | ||
|
|
ed35c4f74e | ||
|
|
9cd3e2d494 | ||
|
|
3345f48986 | ||
|
|
b611d63975 | ||
|
|
fb3866aa1a | ||
|
|
a9f131b645 | ||
|
|
e5728662c5 | ||
|
|
94a97fb0fd | ||
|
|
b5bea6fe7a | ||
|
|
fb9d677d76 | ||
|
|
7c4fc7bd0d | ||
|
|
de992cecf3 | ||
|
|
cd94549606 | ||
|
|
214a6eb5ce | ||
|
|
db5f0aa02d | ||
|
|
ba48ab3659 | ||
|
|
d1538e07d3 | ||
|
|
fe0c033b2d | ||
|
|
2e58dca048 | ||
|
|
d38ab8a439 | ||
|
|
acd7b9ba8c | ||
|
|
56f72b225c | ||
|
|
8bfaf7425a | ||
|
|
77a8726a03 | ||
|
|
119fea3379 | ||
|
|
e54e0d6511 | ||
|
|
a2a88cfafa | ||
|
|
5ff53d08ed | ||
|
|
0ddda4a668 | ||
|
|
d3a76e9f2f | ||
|
|
ea7ec2b5fc | ||
|
|
b9b4ccb180 | ||
|
|
2f15d410fe | ||
|
|
88f5af3e77 | ||
|
|
454ca27c54 | ||
|
|
f536cb3536 | ||
|
|
e6ba7379eb | ||
|
|
f6b01b6e02 | ||
|
|
ce27f8e89c | ||
|
|
a52635f940 | ||
|
|
b608125545 | ||
|
|
631cded0d6 | ||
|
|
43b5140754 | ||
|
|
557a05135e | ||
|
|
618416d0d2 | ||
|
|
9a4ee3db69 | ||
|
|
999dde3fa4 | ||
|
|
1171cce550 | ||
|
|
77e13338ad | ||
|
|
fd35b5ea72 | ||
|
|
f98f25fb6b | ||
|
|
511a49041f | ||
|
|
74be5cfe96 | ||
|
|
1f54b36ece | ||
|
|
d12b77b572 | ||
|
|
4928234785 | ||
|
|
208e3c9933 | ||
|
|
d697381d8b | ||
|
|
cd6b1a2327 | ||
|
|
ff21380099 | ||
|
|
a773531003 | ||
|
|
23ecd43885 | ||
|
|
3415bf5cd3 | ||
|
|
45b9f1190f | ||
|
|
ef1b09671a | ||
|
|
ee282af53e | ||
|
|
455a95d46c | ||
|
|
76666b0d22 | ||
|
|
45fd43682a | ||
|
|
fd801e3323 | ||
|
|
429c6ebb1b | ||
|
|
ea2f24fe23 | ||
|
|
db4a2cfaac | ||
|
|
583223f454 | ||
|
|
f9fcc16f54 | ||
|
|
50ca6ee63d | ||
|
|
56338be13e | ||
|
|
b9ec5ea83c | ||
|
|
389585c47a | ||
|
|
e9583087eb | ||
|
|
57e2090d70 | ||
|
|
5fbf26b8cb | ||
|
|
447c728557 | ||
|
|
a3ca4c81ae | ||
|
|
fb398a5520 | ||
|
|
9a9bb92f91 | ||
|
|
e23a5c24d6 | ||
|
|
1a42a54d98 | ||
|
|
5c91352bae | ||
|
|
3428ea2f18 | ||
|
|
24e5d337a6 | ||
|
|
a2c1413036 | ||
|
|
bab092f04b | ||
|
|
2bf4e6c5c6 | ||
|
|
584add97a3 | ||
|
|
57143a434e | ||
|
|
e31bd7600c | ||
|
|
f02ec8b24b | ||
|
|
b8704f980f | ||
|
|
3accf74687 | ||
|
|
a213ca746c | ||
|
|
349e306d38 | ||
|
|
ca1b1032eb | ||
|
|
a6c9fb0f8b | ||
|
|
c8230c55ee | ||
|
|
55f77613d4 | ||
|
|
c9a1ff45c7 | ||
|
|
c209f66d49 | ||
|
|
3efa02eb81 | ||
|
|
8506f66236 | ||
|
|
cb2826f171 | ||
|
|
0990c9cc3d | ||
|
|
4aa9594a61 | ||
|
|
ed208cf433 | ||
|
|
428faeb756 | ||
|
|
e858edd85c | ||
|
|
e4ab27a292 | ||
|
|
eece5793d6 | ||
|
|
3df737a94f | ||
|
|
0e4c414c2e | ||
|
|
326304db54 | ||
|
|
c8e54524a3 | ||
|
|
d671060a47 | ||
|
|
93dab76da2 | ||
|
|
bbed8e5fae | ||
|
|
e16f8fc7e9 | ||
|
|
86f17094bb | ||
|
|
b1b49758b1 | ||
|
|
4790665759 | ||
|
|
8ede492cba | ||
|
|
5f607cc034 | ||
|
|
3b9f508be9 | ||
|
|
89e381b7ea | ||
|
|
57869b2145 | ||
|
|
46976900d7 | ||
|
|
a1535da117 | ||
|
|
f43d782b5c | ||
|
|
5c443e2f93 | ||
|
|
54f01f63f7 | ||
|
|
c64b4473e4 | ||
|
|
d413a37c1f | ||
|
|
202fb12008 | ||
|
|
59dea63870 | ||
|
|
9a18f2b553 | ||
|
|
4293ec3805 | ||
|
|
f3b616e495 | ||
|
|
003ea24990 | ||
|
|
92d4566a54 | ||
|
|
70a933edc1 | ||
|
|
d2d77f28aa | ||
|
|
39179971c5 | ||
|
|
c06f36e8c2 | ||
|
|
1d2d9d8b99 | ||
|
|
5f529817ef | ||
|
|
7c91bc2f37 | ||
|
|
ef022f5a6d | ||
|
|
54ce00c8b9 | ||
|
|
baabbfb1ea | ||
|
|
28e676ac9a | ||
|
|
21fac9ec7a | ||
|
|
335955820b | ||
|
|
d2b0e7209f | ||
|
|
f8ed21c819 | ||
|
|
9c2143effe | ||
|
|
8a3fa6aff6 | ||
|
|
7e304bb231 | ||
|
|
99d614289e | ||
|
|
b90894c20f | ||
|
|
921834c917 | ||
|
|
83df4451e6 | ||
|
|
2ad9e1bb43 | ||
|
|
c9990e5ca4 | ||
|
|
c95e61db09 | ||
|
|
7bb12ff0ec | ||
|
|
670bfa18de | ||
|
|
130f619b05 | ||
|
|
f900c842cb | ||
|
|
c2844a8f35 | ||
|
|
a864dabbaf | ||
|
|
02786f4801 | ||
|
|
5a4fe266c6 | ||
|
|
b30a4db0b8 | ||
|
|
2e76e07764 | ||
|
|
1be92f5078 | ||
|
|
8afff29cd4 | ||
|
|
9c6090a355 | ||
|
|
27b73227ed | ||
|
|
9582f8380f | ||
|
|
bfeac7e70b | ||
|
|
2050c0b7a8 | ||
|
|
144f9bed69 | ||
|
|
f2b642d944 | ||
|
|
bcdc75953e | ||
|
|
1fabe5a7cf | ||
|
|
fe9a4b7aa3 | ||
|
|
56735dc1c6 | ||
|
|
42287b92f1 | ||
|
|
7d9e642f24 | ||
|
|
b20e10585f | ||
|
|
8438b211a6 | ||
|
|
f94314afec | ||
|
|
4584d23434 | ||
|
|
2791501781 | ||
|
|
6ea798e55b | ||
|
|
0ab6ac569e | ||
|
|
f91d7352a4 | ||
|
|
d644b8fe01 | ||
|
|
5a8042cc10 | ||
|
|
ae910eb731 | ||
|
|
c1158c3175 | ||
|
|
79562e7ad9 | ||
|
|
e3388bea96 | ||
|
|
a3b4a7ef1d | ||
|
|
947b06cd61 | ||
|
|
a3f3561f02 | ||
|
|
48095d38be | ||
|
|
1c6858653a | ||
|
|
648797325e | ||
|
|
af3fa88d67 | ||
|
|
8123effa65 | ||
|
|
554800c06f | ||
|
|
687ce29366 | ||
|
|
c70301572c | ||
|
|
714f58e2c5 | ||
|
|
9bf9dca88a | ||
|
|
0663f25208 | ||
|
|
275d162b81 | ||
|
|
675956a7c4 | ||
|
|
cf1602c0af | ||
|
|
35979ed332 | ||
|
|
6e65ae5306 | ||
|
|
95e716b8ce | ||
|
|
554284ac67 | ||
|
|
fa6102bbad | ||
|
|
f28d5f19a7 | ||
|
|
34d59c7741 | ||
|
|
21d432a3ca | ||
|
|
d444935140 | ||
|
|
9de9d96e35 | ||
|
|
5932558ca2 | ||
|
|
7b22adb72e | ||
|
|
0db5d062be | ||
|
|
678d510e29 | ||
|
|
1fc3307d22 | ||
|
|
45c17ba949 | ||
|
|
15bd1d9006 | ||
|
|
b4715f0931 | ||
|
|
6f24a2a88c | ||
|
|
fcbecf895a | ||
|
|
5abe8a109c | ||
|
|
ee6d0af795 | ||
|
|
0dc82b6a28 | ||
|
|
a530eda9fc | ||
|
|
3fa39798e5 | ||
|
|
b7f8832633 | ||
|
|
2add8d671a | ||
|
|
d5d1fcf331 | ||
|
|
9007501d81 | ||
|
|
fc12a8f549 | ||
|
|
86f03b3399 | ||
|
|
80ad0e7f68 | ||
|
|
ea970be6f2 | ||
|
|
4bd0b96a2d | ||
|
|
c7f0436ec0 | ||
|
|
ecc788fd79 | ||
|
|
8ea9d5685d | ||
|
|
c2bd2f0672 | ||
|
|
424b7964b4 | ||
|
|
98394fdc63 | ||
|
|
625e90518e | ||
|
|
d446191cf4 | ||
|
|
ea2557274f | ||
|
|
1bcca566ab | ||
|
|
cf365635ef | ||
|
|
df6a93da5f | ||
|
|
433512a256 | ||
|
|
e0fe78b82e | ||
|
|
d3a84690f2 | ||
|
|
3df4b4dc57 | ||
|
|
b2801f3a40 | ||
|
|
e1bdfd7e4e | ||
|
|
5584c12d0a | ||
|
|
91bd02157c | ||
|
|
02d2b88a54 | ||
|
|
6ae5c5e6ce | ||
|
|
123d2f6120 | ||
|
|
3ada10c3f4 | ||
|
|
b21a928028 | ||
|
|
374cf08086 | ||
|
|
15a85bb873 | ||
|
|
4b12678fa4 | ||
|
|
b2d4bea1d0 | ||
|
|
6df3a7d4b5 | ||
|
|
6964bf7c8a | ||
|
|
965424799d | ||
|
|
f7de2ead40 | ||
|
|
260ba19e44 | ||
|
|
5caff5d28e | ||
|
|
8fa490c938 | ||
|
|
8e3cc0df0c | ||
|
|
1a5a4cf72d | ||
|
|
6c5b7bbed0 | ||
|
|
f9eee6a864 | ||
|
|
4ad0fe5653 | ||
|
|
a02823ca38 | ||
|
|
513f8e66f5 | ||
|
|
0cecc168b6 | ||
|
|
6f7281b0f5 | ||
|
|
c7022bd285 | ||
|
|
e89e3d2e1b | ||
|
|
574fb6804f | ||
|
|
caf75fafdf | ||
|
|
bc74fb63d1 | ||
|
|
b576a87d61 | ||
|
|
6e81d8acec | ||
|
|
c67a53d156 | ||
|
|
bf5ea81b40 | ||
|
|
1261b8670f | ||
|
|
17dad33f8b | ||
|
|
1d5c160e1d | ||
|
|
f04b7fa365 | ||
|
|
fa011fbdce | ||
|
|
759c5374d9 | ||
|
|
f631acdf18 | ||
|
|
b2dfd8ab11 | ||
|
|
43f4803da7 | ||
|
|
019d8220b8 | ||
|
|
b946010bdb | ||
|
|
c3097b12c3 | ||
|
|
12a53710c3 | ||
|
|
983326e610 | ||
|
|
b4eb707b38 | ||
|
|
e44f34f0a9 | ||
|
|
3c762adbf4 | ||
|
|
ebabd20d09 | ||
|
|
8694e1901a | ||
|
|
0f2875e89a | ||
|
|
74d9921be1 | ||
|
|
41e56adfdb | ||
|
|
4ff1d302d9 | ||
|
|
d6e213d51a | ||
|
|
2a4deeba55 | ||
|
|
24b1d2afcb | ||
|
|
5cea3d824a | ||
|
|
78a8a7d744 | ||
|
|
a3bf85754a | ||
|
|
006b6fd5e8 | ||
|
|
8ff2c42070 | ||
|
|
c5d18c6884 | ||
|
|
48b3621f1e | ||
|
|
fb716eb498 | ||
|
|
5d8e294350 | ||
|
|
8a96d8c24e | ||
|
|
6396d2f922 | ||
|
|
ed7e90451b | ||
|
|
f5990dd5c4 | ||
|
|
f29f615aec | ||
|
|
f1300badb8 | ||
|
|
88a1cddb23 | ||
|
|
d53fbc52d1 | ||
|
|
ec9511c17a | ||
|
|
3f2bb3beae | ||
|
|
c8b96696b0 | ||
|
|
0bb6b53ebc | ||
|
|
7400c2373b | ||
|
|
635329f102 | ||
|
|
b5a2123d1c | ||
|
|
396c558b25 | ||
|
|
60e178d821 | ||
|
|
7769aaccea | ||
|
|
5ff6d0b014 | ||
|
|
7d9a1b5e0c | ||
|
|
127086a50e | ||
|
|
90d14c004f | ||
|
|
8c457c057e | ||
|
|
36215a989a | ||
|
|
74259bd4c6 | ||
|
|
4561b7dce2 | ||
|
|
89d6166dbe | ||
|
|
f451977a04 | ||
|
|
aac05727ed | ||
|
|
c9ae65a9a8 | ||
|
|
f4a9dbb546 | ||
|
|
3eec791584 | ||
|
|
57473da182 | ||
|
|
fd90752a12 | ||
|
|
0d3f5e0c32 | ||
|
|
c98b0aac90 | ||
|
|
3de85975d6 | ||
|
|
962cdef69a | ||
|
|
b301d20488 | ||
|
|
1b2895b0ca | ||
|
|
d6943bb1dd | ||
|
|
51d74503ae | ||
|
|
5eac3cf9cf | ||
|
|
27d6f24c3c | ||
|
|
d929b163db | ||
|
|
571b3fbfa8 | ||
|
|
db05f8eaa3 | ||
|
|
d8eba81efc | ||
|
|
429ef67bbf | ||
|
|
e5d9e69e3e | ||
|
|
dc32bdc474 | ||
|
|
c45b709d54 | ||
|
|
e1be084d98 | ||
|
|
20b8aafe11 | ||
|
|
c719adf235 | ||
|
|
d08a0bdb00 | ||
|
|
8294391ebc | ||
|
|
394c206133 | ||
|
|
2fcd561ff7 | ||
|
|
f95b77fd7a | ||
|
|
7509bf69ca | ||
|
|
d9adec88c8 | ||
|
|
938a1bca0d | ||
|
|
ab757c502c | ||
|
|
6b17388bd8 | ||
|
|
48a933b757 | ||
|
|
6c02bf73b5 | ||
|
|
960d0bcdf2 | ||
|
|
d389e4390f | ||
|
|
55ce83a642 | ||
|
|
300f8f666d | ||
|
|
5d6083dce4 | ||
|
|
82f9f5027f | ||
|
|
4f015f1d96 | ||
|
|
bbe272c35c | ||
|
|
39513448f3 | ||
|
|
bee61bf398 | ||
|
|
010c31cf10 | ||
|
|
d1643b4506 | ||
|
|
623307b348 | ||
|
|
09e8fca132 | ||
|
|
2c96a26d91 | ||
|
|
f639d2aa57 | ||
|
|
5a68eb345f | ||
|
|
603a3d78fc | ||
|
|
cafc6a7226 | ||
|
|
0b068f6d79 | ||
|
|
ec73c916b7 | ||
|
|
110ccb5587 | ||
|
|
d224ae3eb0 | ||
|
|
dd9c0b3a01 | ||
|
|
d2d711c1f8 | ||
|
|
3dd2492926 | ||
|
|
bc1520ec35 | ||
|
|
3033a82c92 | ||
|
|
bb75be7e8e | ||
|
|
b52f2f5a9e | ||
|
|
5bcfb958f0 | ||
|
|
5f52963ce0 | ||
|
|
3f76be2287 | ||
|
|
92aa65a839 | ||
|
|
bd5337a2c2 | ||
|
|
990d5815f2 | ||
|
|
c1d51cc196 | ||
|
|
f5b871f8f5 | ||
|
|
bc6b84f900 | ||
|
|
5ee79c8148 | ||
|
|
e4706dd3ba | ||
|
|
3c59a870e7 | ||
|
|
ae6ad8870d | ||
|
|
07fed0acce | ||
|
|
7dd99f3d18 | ||
|
|
03d8cfb401 | ||
|
|
ccb981e6ce | ||
|
|
984d5c716b | ||
|
|
43121a08bd | ||
|
|
54c7f16c4c | ||
|
|
6cd2674f2a | ||
|
|
602947a3d7 | ||
|
|
5048963aa2 | ||
|
|
8d16e2b59b | ||
|
|
4accbef6a9 | ||
|
|
2e9d95b96a | ||
|
|
03dfd1b96f | ||
|
|
ee1ccb7f01 |
30
.gitattributes
vendored
@@ -1,6 +1,24 @@
|
||||
src/static/fontawesome/* linguist-vendored
|
||||
src/static/lightbox/* linguist-vendored
|
||||
src/static/typeahead/* linguist-vendored
|
||||
src/static/moment/* linguist-vendored
|
||||
src/static/datetimepicker/* linguist-vendored
|
||||
src/static/charts/* linguist-vendored
|
||||
src/pretix/static/fontawesome/* linguist-vendored
|
||||
src/pretix/static/lightbox/* linguist-vendored
|
||||
src/pretix/static/typeahead/* linguist-vendored
|
||||
src/pretix/static/moment/* linguist-vendored
|
||||
src/pretix/static/datetimepicker/* linguist-vendored
|
||||
src/pretix/static/colorpicker/* linguist-vendored
|
||||
src/pretix/static/fileupload/* linguist-vendored
|
||||
src/pretix/static/vuejs/* linguist-vendored
|
||||
src/pretix/static/select2/* linguist-vendored
|
||||
src/pretix/static/charts/* linguist-vendored
|
||||
src/pretix/static/rrule/* linguist-vendored
|
||||
src/pretix/static/iframeresizer/* linguist-vendored
|
||||
src/pretix/static/pdfjs/* linguist-vendored
|
||||
src/pretix/static/fabric/* linguist-vendored
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.eot binary
|
||||
*.otf binary
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.zip binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.jpg binary
|
||||
|
||||
2
.gitignore
vendored
@@ -21,4 +21,6 @@ pretixeu/
|
||||
local/
|
||||
.project
|
||||
.pydevproject
|
||||
.DS_Store
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,37 @@ before_script:
|
||||
tests:
|
||||
stage: test
|
||||
script:
|
||||
- virtualenv-3.4 env
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh style
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh tests
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh doctests
|
||||
tags:
|
||||
- python3
|
||||
except:
|
||||
- pypi
|
||||
pypi:
|
||||
stage: release
|
||||
script:
|
||||
- cp /keys/.pypirc ~/.pypirc
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt
|
||||
- cd src
|
||||
- python setup.py sdist
|
||||
- pip install dist/pretix-*.tar.gz
|
||||
- python -m pretix migrate
|
||||
- python -m pretix check
|
||||
- python setup.py sdist upload
|
||||
- python setup.py bdist_wheel upload
|
||||
tags:
|
||||
- python3
|
||||
only:
|
||||
- pypi
|
||||
artifacts:
|
||||
paths:
|
||||
- src/dist/
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- release
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
-r src/requirements/py34.txt
|
||||
-r doc/requirements.txt
|
||||
|
||||
31
.travis.sh
@@ -15,32 +15,45 @@ if [ "$PRETIX_CONFIG_FILE" == "tests/travis_postgres.cfg" ]; then
|
||||
fi
|
||||
|
||||
if [ "$1" == "style" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt
|
||||
cd src
|
||||
flake8 .
|
||||
isort -c -rc .
|
||||
isort -c -rc -df .
|
||||
fi
|
||||
if [ "$1" == "doctests" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur doc/requirements.txt -r src/requirements/py34.txt
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur doc/requirements.txt
|
||||
cd doc
|
||||
make doctest
|
||||
fi
|
||||
if [ "$1" == "doc-spelling" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur doc/requirements.txt
|
||||
cd doc
|
||||
make spelling
|
||||
if [ -s _build/spelling/output.txt ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ "$1" == "translation-spelling" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements/dev.txt
|
||||
cd src
|
||||
potypo
|
||||
fi
|
||||
if [ "$1" == "tests" ]; then
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt pytest-xdist
|
||||
cd src
|
||||
python manage.py check
|
||||
make all compress
|
||||
py.test --rerun 5 tests
|
||||
py.test --reruns 5 -n 2 tests
|
||||
fi
|
||||
if [ "$1" == "tests-cov" ]; then
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt
|
||||
cd src
|
||||
python manage.py check
|
||||
make all compress
|
||||
coverage run -m py.test --rerun 5 tests && codecov
|
||||
coverage run -m py.test --reruns 5 tests && codecov
|
||||
fi
|
||||
if [ "$1" == "plugins" ]; then
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt
|
||||
cd src
|
||||
python setup.py develop
|
||||
make all compress
|
||||
@@ -50,7 +63,7 @@ if [ "$1" == "plugins" ]; then
|
||||
cd pretix-cartshare
|
||||
python setup.py develop
|
||||
make
|
||||
py.test --rerun 5 tests
|
||||
py.test --reruns 5 tests
|
||||
popd
|
||||
|
||||
fi
|
||||
|
||||
40
.travis.yml
@@ -12,29 +12,31 @@ services:
|
||||
- postgresql
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_sqlite.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
env: JOB=tests-cov PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.4
|
||||
env: JOB=style
|
||||
- python: 3.4
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_sqlite.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
env: JOB=plugins
|
||||
- python: 3.4
|
||||
env: JOB=tests-cov
|
||||
- python: 3.6
|
||||
env: JOB=doc-spelling
|
||||
- python: 3.6
|
||||
env: JOB=translation-spelling
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
apt:
|
||||
packages:
|
||||
- enchant
|
||||
- myspell-de-de
|
||||
- aspell-en
|
||||
branches:
|
||||
except:
|
||||
- /^weblate-.*/
|
||||
|
||||
5
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Code of Conduct
|
||||
===============
|
||||
|
||||
We have a [Code of Conduct](https://docs.pretix.eu/en/latest/development/contribution/codeofconduct.html)
|
||||
in place that applies to all project contributions, including issues, pull requests, etc.
|
||||
13
Dockerfile
@@ -1,11 +1,9 @@
|
||||
FROM debian:jessie
|
||||
FROM python:3.6
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y python3 git python3-pip \
|
||||
libxml2-dev libxslt1-dev python-dev python-virtualenv locales libffi-dev \
|
||||
build-essential python3-dev zlib1g-dev libssl-dev gettext \
|
||||
libpq-dev libmysqlclient-dev libmemcached-dev libjpeg-dev \
|
||||
aqbanking-tools supervisor nginx sudo \
|
||||
apt-get install -y git libxml2-dev libxslt1-dev python-dev python-virtualenv locales \
|
||||
libffi-dev build-essential python3-dev zlib1g-dev libssl-dev gettext libpq-dev \
|
||||
default-libmysqlclient-dev libmemcached-dev libjpeg-dev supervisor nginx sudo \
|
||||
--no-install-recommends && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
@@ -33,8 +31,7 @@ RUN chmod +x /usr/local/bin/pretix && \
|
||||
cd /pretix/src && \
|
||||
rm -f pretix.cfg && \
|
||||
pip3 install -r requirements.txt -r requirements/mysql.txt -r requirements/postgres.txt \
|
||||
-r requirements/memcached.txt -r requirements/redis.txt \
|
||||
-r requirements/py34.txt gunicorn && \
|
||||
-r requirements/memcached.txt -r requirements/redis.txt gunicorn && \
|
||||
mkdir -p data && \
|
||||
chown -R pretixuser:pretixuser /pretix /data data && \
|
||||
sudo -u pretixuser make production
|
||||
|
||||
@@ -40,6 +40,14 @@ Contributing
|
||||
If you want to contribute to pretix, please read the `developer documentation`_
|
||||
in our documentation. If you have any further questions, please do not hesitate to ask!
|
||||
|
||||
.. image:: https://translate.pretix.eu/widgets/pretix/-/pretix/multi-blue.svg
|
||||
:target: https://translate.pretix.eu/engage/pretix/
|
||||
|
||||
Code of Conduct
|
||||
---------------
|
||||
We have a `Code of Conduct`_ in place that applies to all project contributions,
|
||||
including issues, pull requests, etc.
|
||||
|
||||
License
|
||||
-------
|
||||
The code in this repository is published under the terms of the Apache License.
|
||||
@@ -50,5 +58,6 @@ AUTHORS file for a list of all the awesome folks who contributed to this project
|
||||
|
||||
.. _installation guide: https://docs.pretix.eu/en/latest/admin/installation/index.html
|
||||
.. _developer documentation: https://docs.pretix.eu/en/latest/development/index.html
|
||||
.. _Code of Conduct: https://docs.pretix.eu/en/latest/development/contribution/codeofconduct.html
|
||||
.. _pretix.eu: https://pretix.eu
|
||||
.. _blog: https://pretix.eu/about/en/blog/
|
||||
|
||||
@@ -22,9 +22,11 @@ http {
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
access_log /var/log/nginx/access.log private;
|
||||
error_log /var/log/nginx/error.log;
|
||||
add_header Referrer-Policy same-origin;
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
cd /pretix/src
|
||||
export DJANGO_SETTINGS_MODULE=production_settings
|
||||
export DATA_DIR=/data/
|
||||
NUM_WORKERS=10
|
||||
export HOME=/pretix
|
||||
export NUM_WORKERS=$((2 * $(nproc --all)))
|
||||
|
||||
if [ ! -d /data/logs ]; then
|
||||
mkdir /data/logs;
|
||||
|
||||
@@ -23,6 +23,7 @@ autostart=true
|
||||
autorestart=true
|
||||
priority=5
|
||||
user=pretixuser
|
||||
environment=HOME=/pretix
|
||||
|
||||
[program:pretixtask]
|
||||
command=/usr/local/bin/pretix taskworker
|
||||
|
||||
@@ -175,3 +175,9 @@ pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
||||
|
||||
spelling:
|
||||
$(SPHINXBUILD) -b spelling $(ALLSPHINXOPTS) $(BUILDDIR)/spelling
|
||||
@echo
|
||||
@echo "Spelling check finished, look at the results in " \
|
||||
"$(BUILDDIR)/spelling/output.txt."
|
||||
|
||||
160
doc/_templates/index.html
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
{% extends "layout.html" %}
|
||||
{% set title = 'Overview' %}
|
||||
{% block body %}
|
||||
<h1>Welcome to pretix' documentation!</h1>
|
||||
<p>
|
||||
We work hard to make this website contain all information that you need to use, run, understand, and improve
|
||||
pretix. Of course, this documentation will never be perfect or complete, but if there is anything unclear
|
||||
or anything specific that you miss here, that's a bug and we'd be happy if you'd
|
||||
<a href="https://github.com/pretix/pretix/issues/new">let us know</a>.
|
||||
</p>
|
||||
|
||||
<h2>Documentation structure</h2>
|
||||
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="user/index.html">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="user/index.html">
|
||||
<strong>User Guide</strong>
|
||||
</a>
|
||||
<p>Go here to find information on how to configure and use pretix as an event organizer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="admin/index.html">
|
||||
<span class="fa fa-server fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="admin/index.html">
|
||||
<strong>Administrator docs</strong>
|
||||
</a>
|
||||
<p>Find out how to install pretix on your own server and how to maintain an installation of pretix.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="api/index.html">
|
||||
<span class="fa fa-plug fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="api/index.html">
|
||||
<strong>REST API</strong>
|
||||
</a>
|
||||
<p>
|
||||
Documentation and reference of the RESTful API exposed by pretix for interaction with external
|
||||
components.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="development/index.html">
|
||||
<span class="fa fa-wrench fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="development/index.html">
|
||||
<strong>Developer docs</strong>
|
||||
</a>
|
||||
<p>Get information on how to contribute to pretix itself and how to build plugins that interact with
|
||||
pretix.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="plugins/index.html">
|
||||
<span class="fa fa-puzzle-piece fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="plugins/index.html">
|
||||
<strong>Plugin docs</strong>
|
||||
</a>
|
||||
<p>Documentation and details on plugins that ship with pretix or are officially supported.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="contents.html">
|
||||
<span class="fa fa-list fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="contents.html">
|
||||
<strong>Table of contents</strong>
|
||||
</a>
|
||||
<p>Detailled overview of everything contained in this documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<h2>Useful links</h2>
|
||||
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://pretix.eu" target="_blank">
|
||||
<span class="fa fa-globe fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://pretix.eu" target="_blank">
|
||||
<strong>Project website</strong>
|
||||
</a>
|
||||
<p>pretix.eu is the central entry-point to the pretix project and also the home of the commercial hosting
|
||||
service available.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://github.com/pretix/pretix" target="_blank">
|
||||
<span class="fa fa-github fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://github.com/pretix/pretix" target="_blank">
|
||||
<strong>GitHub repository</strong>
|
||||
</a>
|
||||
<p>Our main source code repository contains all code that is part of pretix as well as some plugins and the
|
||||
source for this documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://pretix.eu/about/en/blog/" target="_blank">
|
||||
<span class="fa fa-newspaper-o fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://pretix.eu/about/en/blog/" target="_blank">
|
||||
<strong>Project blog</strong>
|
||||
</a>
|
||||
<p>This important information source contains all release notes for all stable releases of pretix as well as
|
||||
general news on pretix as a project.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<span class="fa fa-twitter fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<strong>Twitter</strong>
|
||||
</a>
|
||||
<p>Keep in touch and stay up to date by following our project account on Twitter.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
{% endblock %}
|
||||
16
doc/_themes/pretix_theme/__init__.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"""pretix sphinx theme.
|
||||
|
||||
Based on sphinx-rtd-theme
|
||||
Based on https://github.com/ryan-roemer/sphinx-bootstrap-theme.
|
||||
|
||||
"""
|
||||
import os
|
||||
|
||||
__version__ = '0.1.0'
|
||||
__version_full__ = __version__
|
||||
|
||||
|
||||
def get_html_theme_path():
|
||||
"""Return list of HTML theme paths."""
|
||||
cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
return cur_dir
|
||||
82
doc/_themes/pretix_theme/breadcrumbs.html
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #}
|
||||
|
||||
{% if page_source_suffix %}
|
||||
{% set suffix = page_source_suffix %}
|
||||
{% else %}
|
||||
{% set suffix = source_suffix %}
|
||||
{% endif %}
|
||||
|
||||
{% if meta is defined and meta is not none %}
|
||||
{% set check_meta = True %}
|
||||
{% else %}
|
||||
{% set check_meta = False %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'github_url' in meta %}
|
||||
{% set display_github = True %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'bitbucket_url' in meta %}
|
||||
{% set display_bitbucket = True %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'gitlab_url' in meta %}
|
||||
{% set display_gitlab = True %}
|
||||
{% endif %}
|
||||
|
||||
<div role="navigation" aria-label="breadcrumbs navigation">
|
||||
|
||||
<ul class="wy-breadcrumbs">
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{{ pathto(master_doc) }}">{{ _('Docs') }}</a> »</li>
|
||||
{% for doc in parents %}
|
||||
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> »</li>
|
||||
{% endfor %}
|
||||
<li>{{ title }}</li>
|
||||
{% endblock %}
|
||||
{% block breadcrumbs_aside %}
|
||||
<li class="wy-breadcrumbs-aside">
|
||||
{% if pagename != "search" %}
|
||||
{% if display_github %}
|
||||
{% if check_meta and 'github_url' in meta %}
|
||||
<!-- User defined GitHub URL -->
|
||||
<a href="{{ meta['github_url'] }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
|
||||
{% else %}
|
||||
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
|
||||
{% endif %}
|
||||
{% elif display_bitbucket %}
|
||||
{% if check_meta and 'bitbucket_url' in meta %}
|
||||
<!-- User defined Bitbucket URL -->
|
||||
<a href="{{ meta['bitbucket_url'] }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
|
||||
{% else %}
|
||||
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
|
||||
{% endif %}
|
||||
{% elif display_gitlab %}
|
||||
{% if check_meta and 'gitlab_url' in meta %}
|
||||
<!-- User defined GitLab URL -->
|
||||
<a href="{{ meta['gitlab_url'] }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
|
||||
{% else %}
|
||||
<a href="https://{{ gitlab_host|default("gitlab.com") }}/{{ gitlab_user }}/{{ gitlab_repo }}/blob/{{ gitlab_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
|
||||
{% endif %}
|
||||
{% elif show_source and source_url_prefix %}
|
||||
<a href="{{ source_url_prefix }}{{ pagename }}{{ suffix }}">{{ _('View page source') }}</a>
|
||||
{% elif show_source and has_source and sourcename %}
|
||||
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> {{ _('View page source') }}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
{% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
|
||||
<div class="rst-breadcrumbs-buttons" role="navigation" aria-label="breadcrumb navigation">
|
||||
{% if next %}
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr/>
|
||||
</div>
|
||||
52
doc/_themes/pretix_theme/footer.html
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<footer>
|
||||
{% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
{% if next %}
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n" rel="next">{{ _('Next') }} <span class="fa fa-arrow-circle-right"></span></a>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> {{ _('Previous') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr/>
|
||||
|
||||
<div role="contentinfo">
|
||||
<p>
|
||||
{%- if show_copyright %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
{% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
|
||||
{%- else %}
|
||||
{% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if build_id and build_url %}
|
||||
{% trans build_url=build_url, build_id=build_id %}
|
||||
<span class="build">
|
||||
Build
|
||||
<a href="{{ build_url }}">{{ build_id }}</a>.
|
||||
</span>
|
||||
{% endtrans %}
|
||||
{%- elif commit %}
|
||||
{% trans commit=commit %}
|
||||
<span class="commit">
|
||||
Revision <code>{{ commit }}</code>.
|
||||
</span>
|
||||
{% endtrans %}
|
||||
{%- elif last_updated %}
|
||||
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{%- if show_sphinx %}
|
||||
<small>{% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a theme that is based on a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}.</small>
|
||||
{%- endif %}
|
||||
|
||||
{%- block extrafooter %} {% endblock %}
|
||||
|
||||
</footer>
|
||||
|
||||
211
doc/_themes/pretix_theme/layout.html
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
{# TEMPLATE VAR SETTINGS #}
|
||||
{%- set url_root = pathto('', 1) %}
|
||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||
{%- if not embedded and docstitle %}
|
||||
{%- set titlesuffix = " — "|safe + docstitle|e %}
|
||||
{%- else %}
|
||||
{%- set titlesuffix = "" %}
|
||||
{%- endif %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
{{ metatags }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
{% endblock %}
|
||||
|
||||
{# FAVICON #}
|
||||
{% if favicon %}
|
||||
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
|
||||
{% endif %}
|
||||
{# CANONICAL URL #}
|
||||
{% if theme_canonical_url %}
|
||||
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
|
||||
{% endif %}
|
||||
|
||||
{# CSS #}
|
||||
|
||||
{# OPENSEARCH #}
|
||||
{% if not embedded %}
|
||||
{% if use_opensearch %}
|
||||
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{# RTD hosts this file, so just load on non RTD builds #}
|
||||
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
|
||||
|
||||
{% for cssfile in css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{% for cssfile in extra_css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{%- block linktags %}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}"
|
||||
href="{{ pathto('about') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('genindex') %}
|
||||
<link rel="index" title="{{ _('Index') }}"
|
||||
href="{{ pathto('genindex') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('search') %}
|
||||
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
|
||||
{%- endif %}
|
||||
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
|
||||
{%- if parents %}
|
||||
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- if prev %}
|
||||
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- block extrahead %} {% endblock %}
|
||||
|
||||
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
|
||||
<script src="{{ pathto('_static/js/modernizr.min.js', 1) }}"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="wy-body-for-nav" role="document">
|
||||
|
||||
{% block extrabody %} {% endblock %}
|
||||
<div class="wy-grid-for-nav">
|
||||
|
||||
{# SIDE NAV, TOGGLES ON MOBILE #}
|
||||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||||
<div class="wy-side-scroll">
|
||||
<div class="wy-side-nav-search">
|
||||
{% block sidebartitle %}
|
||||
|
||||
{% if logo and theme_logo_only %}
|
||||
<a href="{{ pathto('index') }}">
|
||||
{% else %}
|
||||
<a href="{{ pathto('index') }}" class="icon icon-home"> {{ project }}
|
||||
{% endif %}
|
||||
|
||||
{% if logo %}
|
||||
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
|
||||
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% include "searchbox.html" %}
|
||||
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||||
{% block menu %}
|
||||
{#
|
||||
The singlehtml builder doesn't handle this toctree call when the
|
||||
toctree is empty. Skip building this for now.
|
||||
#}
|
||||
{% if 'singlehtml' not in builder %}
|
||||
{% set global_toc = toctree(maxdepth=theme_navigation_depth|int, collapse=theme_collapse_navigation, includehidden=True) %}
|
||||
{% endif %}
|
||||
{% if global_toc %}
|
||||
{{ global_toc }}
|
||||
{% else %}
|
||||
<!-- Local TOC -->
|
||||
<div class="local-toc">{{ toc }}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% if theme_display_version %}
|
||||
{%- set nav_version = version %}
|
||||
{% if READTHEDOCS and current_version %}
|
||||
{%- set nav_version = current_version %}
|
||||
{% endif %}
|
||||
{% if nav_version %}
|
||||
<div class="version">
|
||||
{{ nav_version }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||
|
||||
{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
|
||||
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
|
||||
{% block mobile_nav %}
|
||||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||
<a href="{{ pathto('index') }}">{{ project }}</a>
|
||||
{% endblock %}
|
||||
</nav>
|
||||
|
||||
|
||||
{# PAGE CONTENT #}
|
||||
<div class="wy-nav-content">
|
||||
<div class="rst-content">
|
||||
{% include "breadcrumbs.html" %}
|
||||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||
<div itemprop="articleBody">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
<div class="articleComments">
|
||||
{% block comments %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "footer.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
{% include "versions.html" %}
|
||||
|
||||
{% if not embedded %}
|
||||
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT:'{{ url_root }}',
|
||||
VERSION:'{{ release|e }}',
|
||||
COLLAPSE_INDEX:false,
|
||||
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
|
||||
HAS_SOURCE: {{ has_source|lower }},
|
||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||
};
|
||||
</script>
|
||||
{%- for scriptfile in script_files %}
|
||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||
{%- endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{# RTD hosts this file, so just load on non RTD builds #}
|
||||
{% if not READTHEDOCS %}
|
||||
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
|
||||
{% endif %}
|
||||
|
||||
{# STICKY NAVIGATION #}
|
||||
{% if theme_sticky_navigation %}
|
||||
<script type="text/javascript">
|
||||
jQuery(function () {
|
||||
SphinxRtdTheme.StickyNav.enable();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{%- block footer %} {% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
209
doc/_themes/pretix_theme/layout_old.html
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
{#
|
||||
basic/layout.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Master layout template for Sphinx themes.
|
||||
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- block doctype -%}
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
{%- endblock %}
|
||||
{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %}
|
||||
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
|
||||
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
|
||||
(sidebars != []) %}
|
||||
{%- set url_root = pathto('', 1) %}
|
||||
{# XXX necessary? #}
|
||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||
{%- if not embedded and docstitle %}
|
||||
{%- set titlesuffix = " — "|safe + docstitle|e %}
|
||||
{%- else %}
|
||||
{%- set titlesuffix = "" %}
|
||||
{%- endif %}
|
||||
|
||||
{%- macro relbar() %}
|
||||
<div class="related">
|
||||
<h3>{{ _('Navigation') }}</h3>
|
||||
<ul>
|
||||
{%- for rellink in rellinks %}
|
||||
<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
|
||||
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
|
||||
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
|
||||
{%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
|
||||
{%- endfor %}
|
||||
{%- block rootrellink %}
|
||||
<li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
|
||||
{%- endblock %}
|
||||
{%- for parent in parents %}
|
||||
<li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
|
||||
{%- endfor %}
|
||||
{%- block relbaritems %} {% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro sidebar() %}
|
||||
{%- if render_sidebar %}
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
{%- block sidebarlogo %}
|
||||
{%- if logo %}
|
||||
<p class="logo"><a href="{{ pathto(master_doc) }}">
|
||||
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
|
||||
</a></p>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- if sidebars != None %}
|
||||
{#- new style sidebar: explicitly include/exclude templates #}
|
||||
{%- for sidebartemplate in sidebars %}
|
||||
{%- include sidebartemplate %}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
{#- old style sidebars: using blocks -- should be deprecated #}
|
||||
{%- block sidebartoc %}
|
||||
{%- include "localtoc.html" %}
|
||||
{%- endblock %}
|
||||
{%- block sidebarrel %}
|
||||
{%- include "relations.html" %}
|
||||
{%- endblock %}
|
||||
{%- block sidebarsourcelink %}
|
||||
{%- include "sourcelink.html" %}
|
||||
{%- endblock %}
|
||||
{%- if customsidebar %}
|
||||
{%- include customsidebar %}
|
||||
{%- endif %}
|
||||
{%- block sidebarsearch %}
|
||||
{%- include "searchbox.html" %}
|
||||
{%- endblock %}
|
||||
{%- endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro script() %}
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '{{ url_root }}',
|
||||
VERSION: '{{ release|e }}',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
||||
HAS_SOURCE: {{ has_source|lower }},
|
||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||
};
|
||||
</script>
|
||||
{%- for scriptfile in script_files %}
|
||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro css() %}
|
||||
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
|
||||
{%- for cssfile in css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
|
||||
{{ metatags }}
|
||||
{%- block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
{%- endblock %}
|
||||
{{ css() }}
|
||||
{%- if not embedded %}
|
||||
{{ script() }}
|
||||
{%- if use_opensearch %}
|
||||
<link rel="search" type="application/opensearchdescription+xml"
|
||||
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
|
||||
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
|
||||
{%- endif %}
|
||||
{%- if favicon %}
|
||||
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
|
||||
{%- endif %}
|
||||
{%- if theme_canonical_url %}
|
||||
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- block linktags %}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('genindex') %}
|
||||
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('search') %}
|
||||
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
|
||||
{%- endif %}
|
||||
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
|
||||
{%- if parents %}
|
||||
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if prev %}
|
||||
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- block extrahead %} {% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{%- block header %}{% endblock %}
|
||||
|
||||
{%- block relbar1 %}{{ relbar() }}{% endblock %}
|
||||
|
||||
{%- block content %}
|
||||
{%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
|
||||
|
||||
<div class="document">
|
||||
{%- block document %}
|
||||
<div class="documentwrapper">
|
||||
{%- if render_sidebar %}
|
||||
<div class="bodywrapper">
|
||||
{%- endif %}
|
||||
<div class="body">
|
||||
{% block body %} {% endblock %}
|
||||
</div>
|
||||
{%- if render_sidebar %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
</div>
|
||||
{%- endblock %}
|
||||
|
||||
{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
{%- endblock %}
|
||||
|
||||
{%- block relbar2 %}{{ relbar() }}{% endblock %}
|
||||
|
||||
{%- block footer %}
|
||||
<div class="footer">
|
||||
{%- if show_copyright %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
{% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
|
||||
{%- else %}
|
||||
{% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if last_updated %}
|
||||
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- if show_sphinx %}
|
||||
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
</div>
|
||||
<p>asdf asdf asdf asdf 22</p>
|
||||
{%- endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
50
doc/_themes/pretix_theme/search.html
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{#
|
||||
basic/search.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Template for the search page.
|
||||
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- extends "layout.html" %}
|
||||
{% set title = _('Search') %}
|
||||
{% set script_files = script_files + ['_static/searchtools.js'] %}
|
||||
{% block footer %}
|
||||
<script type="text/javascript">
|
||||
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
|
||||
</script>
|
||||
{# this is used when loading the search index using $.ajax fails,
|
||||
such as on Chrome for documents on localhost #}
|
||||
<script type="text/javascript" id="searchindexloader"></script>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<noscript>
|
||||
<div id="fallback" class="admonition warning">
|
||||
<p class="last">
|
||||
{% trans %}Please activate JavaScript to enable the search
|
||||
functionality.{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
{% if search_performed %}
|
||||
<h2>{{ _('Search Results') }}</h2>
|
||||
{% if not search_results %}
|
||||
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div id="search-results">
|
||||
{% if search_results %}
|
||||
<ul>
|
||||
{% for href, caption, context in search_results %}
|
||||
<li>
|
||||
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
|
||||
<p class="context">{{ context|e }}</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
9
doc/_themes/pretix_theme/searchbox.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{%- if builder != 'singlehtml' %}
|
||||
<div role="search">
|
||||
<form id="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
|
||||
<input type="text" name="q" placeholder="{{ _('Search docs') }}" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
</div>
|
||||
{%- endif %}
|
||||
2
doc/_themes/pretix_theme/static/css/badge_only.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
|
||||
/*# sourceMappingURL=badge_only.css.map */
|
||||
6101
doc/_themes/pretix_theme/static/css/pretix.css
vendored
Normal file
4
doc/_themes/pretix_theme/static/js/modernizr.min.js
vendored
Normal file
169
doc/_themes/pretix_theme/static/js/theme.js
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"sphinx-rtd-theme":[function(require,module,exports){
|
||||
var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery');
|
||||
|
||||
// Sphinx theme nav state
|
||||
function ThemeNav () {
|
||||
|
||||
var nav = {
|
||||
navBar: null,
|
||||
win: null,
|
||||
winScroll: false,
|
||||
winResize: false,
|
||||
linkScroll: false,
|
||||
winPosition: 0,
|
||||
winHeight: null,
|
||||
docHeight: null,
|
||||
isRunning: false
|
||||
};
|
||||
|
||||
nav.enable = function () {
|
||||
var self = this;
|
||||
|
||||
if (!self.isRunning) {
|
||||
self.isRunning = true;
|
||||
jQuery(function ($) {
|
||||
self.init($);
|
||||
|
||||
self.reset();
|
||||
self.win.on('hashchange', self.reset);
|
||||
|
||||
// Set scroll monitor
|
||||
self.win.on('scroll', function () {
|
||||
if (!self.linkScroll) {
|
||||
self.winScroll = true;
|
||||
}
|
||||
});
|
||||
setInterval(function () { if (self.winScroll) self.onScroll(); }, 25);
|
||||
|
||||
// Set resize monitor
|
||||
self.win.on('resize', function () {
|
||||
self.winResize = true;
|
||||
});
|
||||
setInterval(function () { if (self.winResize) self.onResize(); }, 25);
|
||||
self.onResize();
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
nav.init = function ($) {
|
||||
var doc = $(document),
|
||||
self = this;
|
||||
|
||||
this.navBar = $('div.wy-side-scroll:first');
|
||||
this.win = $(window);
|
||||
|
||||
// Set up javascript UX bits
|
||||
$(document)
|
||||
// Shift nav in mobile when clicking the menu.
|
||||
.on('click', "[data-toggle='wy-nav-top']", function() {
|
||||
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
})
|
||||
|
||||
// Nav menu link click operations
|
||||
.on('click', ".wy-menu-vertical .current ul li a", function() {
|
||||
var target = $(this);
|
||||
// Close menu when you click a link.
|
||||
$("[data-toggle='wy-nav-shift']").removeClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
// Handle dynamic display of l3 and l4 nav lists
|
||||
self.toggleCurrent(target);
|
||||
self.hashChange();
|
||||
})
|
||||
.on('click', "[data-toggle='rst-current-version']", function() {
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift-up");
|
||||
})
|
||||
|
||||
// Make tables responsive
|
||||
$("table.docutils:not(.field-list)")
|
||||
.wrap("<div class='wy-table-responsive'></div>");
|
||||
|
||||
// Add expand links to all parents of nested ul
|
||||
$('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
|
||||
var link = $(this);
|
||||
expand = $('<span class="toctree-expand"></span>');
|
||||
expand.on('click', function (ev) {
|
||||
self.toggleCurrent(link);
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
link.prepend(expand);
|
||||
});
|
||||
};
|
||||
|
||||
nav.reset = function () {
|
||||
// Get anchor from URL and open up nested nav
|
||||
var anchor = encodeURI(window.location.hash);
|
||||
if (anchor) {
|
||||
try {
|
||||
var link = $('.wy-menu-vertical')
|
||||
.find('[href="' + anchor + '"]');
|
||||
// If we didn't find a link, it may be because we clicked on
|
||||
// something that is not in the sidebar (eg: when using
|
||||
// sphinxcontrib.httpdomain it generates headerlinks but those
|
||||
// aren't picked up and placed in the toctree). So let's find
|
||||
// the closest header in the document and try with that one.
|
||||
if (link.length === 0) {
|
||||
var doc_link = $('.document a[href="' + anchor + '"]');
|
||||
var closest_section = doc_link.closest('div.section');
|
||||
// Try again with the closest section entry.
|
||||
link = $('.wy-menu-vertical')
|
||||
.find('[href="#' + closest_section.attr("id") + '"]');
|
||||
|
||||
}
|
||||
$('.wy-menu-vertical li.toctree-l1 li.current')
|
||||
.removeClass('current');
|
||||
link.closest('li.toctree-l2').addClass('current');
|
||||
link.closest('li.toctree-l3').addClass('current');
|
||||
link.closest('li.toctree-l4').addClass('current');
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Error expanding nav for anchor", err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nav.onScroll = function () {
|
||||
this.winScroll = false;
|
||||
var newWinPosition = this.win.scrollTop(),
|
||||
winBottom = newWinPosition + this.winHeight,
|
||||
navPosition = this.navBar.scrollTop(),
|
||||
newNavPosition = navPosition + (newWinPosition - this.winPosition);
|
||||
if (newWinPosition < 0 || winBottom > this.docHeight) {
|
||||
return;
|
||||
}
|
||||
this.navBar.scrollTop(newNavPosition);
|
||||
this.winPosition = newWinPosition;
|
||||
};
|
||||
|
||||
nav.onResize = function () {
|
||||
this.winResize = false;
|
||||
this.winHeight = this.win.height();
|
||||
this.docHeight = $(document).height();
|
||||
};
|
||||
|
||||
nav.hashChange = function () {
|
||||
this.linkScroll = true;
|
||||
this.win.one('hashchange', function () {
|
||||
this.linkScroll = false;
|
||||
});
|
||||
};
|
||||
|
||||
nav.toggleCurrent = function (elem) {
|
||||
var parent_li = elem.closest('li');
|
||||
parent_li.siblings('li.current').removeClass('current');
|
||||
parent_li.siblings().find('li.current').removeClass('current');
|
||||
parent_li.find('> ul li.current').removeClass('current');
|
||||
parent_li.toggleClass('current');
|
||||
}
|
||||
|
||||
return nav;
|
||||
};
|
||||
|
||||
module.exports.ThemeNav = ThemeNav();
|
||||
|
||||
if (typeof(window) != 'undefined') {
|
||||
window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav };
|
||||
}
|
||||
|
||||
},{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]);
|
||||
14
doc/_themes/pretix_theme/theme.conf
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = css/pretix.css
|
||||
|
||||
[options]
|
||||
typekit_id = hiw1hhg
|
||||
analytics_id =
|
||||
sticky_navigation = False
|
||||
logo_only =
|
||||
collapse_navigation = False
|
||||
display_version = True
|
||||
navigation_depth = 4
|
||||
prev_next_buttons_location = bottom
|
||||
canonical_url =
|
||||
37
doc/_themes/pretix_theme/versions.html
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{% if READTHEDOCS %}
|
||||
{# Add rst-badge after rst-versions for small badge style. #}
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Read the Docs</span>
|
||||
v: {{ current_version }}
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
<dl>
|
||||
<dt>{{ _('Versions') }}</dt>
|
||||
{% for slug, url in versions %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{{ _('Downloads') }}</dt>
|
||||
{% for type, url in downloads %}
|
||||
<dd><a href="{{ url }}">{{ type }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{{ _('On Read the Docs') }}</dt>
|
||||
<dd>
|
||||
<a href="//{{ PRODUCTION_DOMAIN }}/projects/{{ slug }}/?fromdocs={{ slug }}">{{ _('Project Home') }}</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="//{{ PRODUCTION_DOMAIN }}/builds/{{ slug }}/?fromdocs={{ slug }}">{{ _('Builds') }}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr/>
|
||||
{% trans %}Free document hosting provided by <a href="http://www.readthedocs.org">Read the Docs</a>.{% endtrans %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
.. _`config`:
|
||||
|
||||
.. spelling:: Galera
|
||||
|
||||
Configuration file
|
||||
==================
|
||||
|
||||
@@ -10,9 +12,10 @@ at the following locations. It will try to read the file from the specified path
|
||||
the following order. The file that is found *last* will override the settings from
|
||||
the files found before.
|
||||
|
||||
1. ``/etc/pretix/pretix.cfg``
|
||||
2. ``~/.pretix.cfg``
|
||||
3. ``pretix.cfg`` in the current working directory
|
||||
1. ``PRETIX_CONFIG_FILE`` environment variable
|
||||
2. ``/etc/pretix/pretix.cfg``
|
||||
3. ``~/.pretix.cfg``
|
||||
4. ``pretix.cfg`` in the current working directory
|
||||
|
||||
The file is expected to be in the INI format as specified in the `Python documentation`_.
|
||||
|
||||
@@ -44,12 +47,16 @@ Example::
|
||||
|
||||
``datadir``
|
||||
The local path to a data directory that will be used for storing user uploads and similar
|
||||
data. Defaults to thea value of the environment variable ``DATA_DIR`` or ``data``.
|
||||
data. Defaults to the value of the environment variable ``DATA_DIR`` or ``data``.
|
||||
|
||||
``plugins_default``
|
||||
A comma-separated list of plugins that are enabled by default for all new events.
|
||||
Defaults to ``pretix.plugins.sendmail,pretix.plugins.statistics``.
|
||||
|
||||
``plugins_exclude``
|
||||
A comma-separated list of plugins that are not available even though they are installed.
|
||||
Defaults to an empty string.
|
||||
|
||||
``cookie_domain``
|
||||
The cookie domain to be set. Defaults to ``None``.
|
||||
|
||||
@@ -59,6 +66,18 @@ Example::
|
||||
``password_reset``
|
||||
Enables or disables password reset. Defaults to ``on``.
|
||||
|
||||
``long_sessions``
|
||||
Enables or disables the "keep me logged in" button. Defaults to ``on``.
|
||||
|
||||
``ecb_rates``
|
||||
By default, pretix periodically downloads a XML file from the European Central Bank to retrieve exchange rates
|
||||
that are used to print tax amounts in the customer currency on invoices for some currencies. Set to ``off`` to
|
||||
disable this feature. Defaults to ``on``.
|
||||
|
||||
``audit_comments``
|
||||
Enables or disables nagging staff users for leaving comments on their sessions for auditability.
|
||||
Defaults to ``off``.
|
||||
|
||||
|
||||
Locale settings
|
||||
---------------
|
||||
@@ -163,14 +182,9 @@ Django settings
|
||||
Example::
|
||||
|
||||
[django]
|
||||
hosts=localhost
|
||||
secret=j1kjps5a5&4ilpn912s7a1!e2h!duz^i3&idu@_907s$wrz@x-
|
||||
debug=off
|
||||
|
||||
``hosts``
|
||||
Comma-separated list of allowed host names for this installation.
|
||||
Default: ``localhost``
|
||||
|
||||
``secret``
|
||||
The secret to be used by Django for signing and verification purposes. If this
|
||||
setting is not provided, pretix will generate a random secret on the first start
|
||||
@@ -282,4 +296,4 @@ various places like order codes, secrets in the ticket QR codes, etc. Example::
|
||||
voucher_code=16
|
||||
|
||||
.. _Python documentation: https://docs.python.org/3/library/configparser.html?highlight=configparser#supported-ini-file-structure
|
||||
.. _Celery documentation: http://docs.celeryproject.org/en/latest/configuration.html
|
||||
.. _Celery documentation: http://docs.celeryproject.org/en/latest/userguide/configuration.html
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
.. _`admindocs`:
|
||||
|
||||
Administrator documentation
|
||||
===========================
|
||||
|
||||
This documentation is for everyone who wants to install pretix on a server.
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ named ``/etc/systemd/system/pretix.service`` with the following content::
|
||||
-v /etc/pretix:/etc/pretix \
|
||||
-v /var/run/redis:/var/run/redis \
|
||||
-v /var/run/mysqld:/var/run/mysqld \
|
||||
pretix/standalone all
|
||||
pretix/standalone:stable all
|
||||
ExecStop=/usr/bin/docker stop %n
|
||||
|
||||
[Install]
|
||||
@@ -239,6 +239,8 @@ Restarting the service can take a few seconds, especially if the update requires
|
||||
Replace ``stable`` above with a specific version number like ``1.0`` or with ``latest`` for the development
|
||||
version, if you want to.
|
||||
|
||||
.. _`docker_plugininstall`:
|
||||
|
||||
Install a plugin
|
||||
----------------
|
||||
|
||||
@@ -246,11 +248,11 @@ To install a plugin, you need to build your own docker image. To do so, create a
|
||||
named ``Dockerfile`` in it. The Dockerfile could look like this (replace ``pretix-passbook`` with the plugins of your
|
||||
choice)::
|
||||
|
||||
FROM pretix/standalone
|
||||
FROM pretix/standalone:stable
|
||||
USER root
|
||||
RUN pip3 install pretix-passbook
|
||||
USER pretixuser
|
||||
RUN make production
|
||||
RUN cd /pretix/src && make production
|
||||
|
||||
Then, go to that directory and build the image::
|
||||
|
||||
@@ -266,8 +268,8 @@ to re-build your custom image after you pulled ``pretix/standalone`` if you want
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _MySQL: https://dev.mysql.com/doc/refman/5.7/en/linux-installation-apt-repo.html
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-9-4-on-debian-8
|
||||
.. _redis: http://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _redis website: http://redis.io/topics/security
|
||||
.. _redis website: https://redis.io/topics/security
|
||||
.. _redis in docker: https://hub.docker.com/r/_/redis/
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
.. highlight:: ini
|
||||
|
||||
.. spelling:: SQL
|
||||
|
||||
General remarks
|
||||
===============
|
||||
|
||||
|
||||
@@ -121,8 +121,7 @@ command if you're running PostgreSQL::
|
||||
|
||||
(venv)$ pip3 install "pretix[mysql]" gunicorn
|
||||
|
||||
If you are running Python 3.4, you also need to ``pip3 install typing``. This is not required on 3.5 or newer.
|
||||
You can find out your Python version using ``python -V``.
|
||||
Note that you need Python 3.5 or newer. You can find out your Python version using ``python -V``.
|
||||
|
||||
We also need to create a data directory::
|
||||
|
||||
@@ -177,7 +176,7 @@ For background tasks we need a second service ``/etc/systemd/system/pretix-worke
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
You can now run the following comamnds to enable and start the services::
|
||||
You can now run the following commands to enable and start the services::
|
||||
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable pretix-web pretix-worker
|
||||
@@ -213,6 +212,9 @@ The following snippet is an example on how to configure a nginx proxy for pretix
|
||||
ssl_certificate /path/to/cert.chain.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
add_header Referrer-Policy same-origin;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8345/;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -273,6 +275,8 @@ To upgrade to a new pretix release, pull the latest code changes and run the fol
|
||||
# systemctl restart pretix-web pretix-worker
|
||||
|
||||
|
||||
.. _`manual_plugininstall`:
|
||||
|
||||
Install a plugin
|
||||
----------------
|
||||
|
||||
@@ -293,6 +297,6 @@ example::
|
||||
.. _pretix.eu: https://pretix.eu/
|
||||
.. _MySQL: https://dev.mysql.com/doc/refman/5.7/en/linux-installation-apt-repo.html
|
||||
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-9-4-on-debian-8
|
||||
.. _redis: http://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
|
||||
@@ -51,7 +51,7 @@ If there is a problem, a status code in the ``5xx`` range will be returned.
|
||||
Performance monitoring
|
||||
----------------------
|
||||
|
||||
If you to generate detailled performance statistics of your pretix installation, there is an
|
||||
If you want to generate detailed performance statistics of your pretix installation, there is an
|
||||
endpoint at ``https://pretix.mydomain.com/metrics`` (no slash at the end) which returns a
|
||||
number of values in the text format understood by monitoring tools like Prometheus_. This data
|
||||
is only collected and exposed if you enable it in the :ref:`metrics-settings` section of your
|
||||
|
||||
9
doc/api/auth.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Authentication
|
||||
==============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
tokenauth
|
||||
oauth
|
||||
deviceauth
|
||||
137
doc/api/deviceauth.rst
Normal file
@@ -0,0 +1,137 @@
|
||||
.. _`rest-deviceauth`:
|
||||
|
||||
Device authentication
|
||||
=====================
|
||||
|
||||
Initializing a new device
|
||||
-------------------------
|
||||
|
||||
Users can create new devices in the "Device" section of their organizer settings. When creating
|
||||
a new device, users can specify a list of events the device is allowed to access. After a new
|
||||
device is created, users will be presented initialization instructions, consisting of an URL
|
||||
and an initialization token. They will also be shown as a QR code with the following contents::
|
||||
|
||||
{"handshake_version": 1, "url": "https://pretix.eu", "token": "kpp4jn8g2ynzonp6"}
|
||||
|
||||
Your application should be able to scan a QR code of this type, or allow to enter the URL and the
|
||||
initialization token manually. The handshake version is not used for manual initialization. When a
|
||||
QR code is scanned with a higher handshake version than you support, you should reject the request
|
||||
and prompt the user to update the client application.
|
||||
|
||||
After your application received the token, you need to call the initialization endpoint to obtain
|
||||
a proper API token. At this point, you need to identify the name and version of your application,
|
||||
as well as the type of underlying hardware. Example:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/device/initialize HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"token": "kpp4jn8g2ynzonp6",
|
||||
"hardware_brand": "Samsung",
|
||||
"hardware_model": "Galaxy S",
|
||||
"software_brand": "pretixdroid",
|
||||
"software_version": "4.0.0"
|
||||
}
|
||||
|
||||
Every initialization token can only be used once. On success, you will receive a response containing
|
||||
information on your device as well as your API token:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"organizer": "foo",
|
||||
"device_id": 5,
|
||||
"unique_serial": "HHZ9LW9JWP390VFZ",
|
||||
"api_token": "1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd",
|
||||
"name": "Bar"
|
||||
}
|
||||
|
||||
Please make sure that you store this ``api_token`` value. We also recommend storing your device ID, your assigned
|
||||
``unique_serial``, and the ``organizer`` you have access to, but that's up to you.
|
||||
|
||||
In case of an error, the response will look like this:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
Content-Type: application/json
|
||||
|
||||
{"token":["This initialization token has already been used."]}
|
||||
|
||||
|
||||
Performing API requests
|
||||
-----------------------
|
||||
|
||||
You need to include the API token with every request to pretix' API in the ``Authorization`` header
|
||||
like the following:
|
||||
|
||||
.. sourcecode:: http
|
||||
:emphasize-lines: 3
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Device 1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd
|
||||
|
||||
Updating the software version
|
||||
-----------------------------
|
||||
|
||||
If your application is updated, we ask you to tell the server about the new version in use. You can do this at the
|
||||
following endpoint:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/device/update HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Content-Type: application/json
|
||||
Authorization: Device 1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd
|
||||
|
||||
{
|
||||
"hardware_brand": "Samsung",
|
||||
"hardware_model": "Galaxy S",
|
||||
"software_brand": "pretixdroid",
|
||||
"software_version": "4.1.0"
|
||||
}
|
||||
|
||||
Creating a new API key
|
||||
----------------------
|
||||
|
||||
If you think your API key might have leaked or just want to be extra cautious, the API allows you to create a new key.
|
||||
The old API key will be invalid immediately. A request for a new key looks like this:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/device/roll HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Device 1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd
|
||||
|
||||
The response will look like the response to the initialization request.
|
||||
|
||||
Removing a device
|
||||
-----------------
|
||||
|
||||
If you want implement a way to to deprovision a device in your software, you can call the ``revoke`` endpoint to
|
||||
invalidate your API key. There is no way to reverse this operation.
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/device/revoke HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Device 1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd
|
||||
|
||||
This can also be done by the user through the web interface.
|
||||
|
||||
Permissions
|
||||
-----------
|
||||
|
||||
Device authentication is currently hardcoded to grant the following permissions:
|
||||
|
||||
* View event meta data and products etc.
|
||||
* View and change orders
|
||||
|
||||
Devices cannot change events or products and cannot access vouchers.
|
||||
183
doc/api/fundamentals.rst
Normal file
@@ -0,0 +1,183 @@
|
||||
Basic concepts
|
||||
==============
|
||||
|
||||
This page describes basic concepts and definition that you need to know to interact
|
||||
with pretix' REST API, such as authentication, pagination and similar definitions.
|
||||
|
||||
.. _`rest-auth`:
|
||||
|
||||
Authentication
|
||||
--------------
|
||||
|
||||
To access the API, you need to present valid authentication credentials. pretix currently
|
||||
supports the following authorization schemes:
|
||||
|
||||
* :ref:`rest-tokenauth`: This is the simplest way and recommended for server-side applications
|
||||
that interact with pretix without user interaction.
|
||||
* :ref:`rest-oauth`: This is the recommended way to use if you write a third-party application
|
||||
that users can connect with their pretix account. It provides the best user experience, but
|
||||
requires user interaction and slightly more implementation effort.
|
||||
* :ref:`rest-deviceauth`: This is the recommended way if you build apps or hardware devices that can
|
||||
connect to pretix, e.g. for processing check-ins or to sell tickets offline. It provides a way
|
||||
to uniquely identify devices and allows for a quick configuration flow inside your software.
|
||||
* Authentication using browser sessions: This is used by the pretix web interface and it is *not*
|
||||
officially supported for use by third-party applications. It might change or be removed at any
|
||||
time without prior notice. If you use it, you need to comply with Django's `CSRF policies`_.
|
||||
|
||||
Permissions
|
||||
-----------
|
||||
|
||||
The API follows pretix team based permissions model. Each organizer can have several teams
|
||||
each with it's own set of permissions. Each team can have any number of API keys attached.
|
||||
|
||||
To access a given endpoint the team the API key belongs to needs to have the corresponding
|
||||
permission for the organizer/event being accessed.
|
||||
|
||||
Possible permissions are:
|
||||
|
||||
* Can create events
|
||||
* Can change event settings
|
||||
* Can change product settings
|
||||
* Can view orders
|
||||
* Can change orders
|
||||
* Can view vouchers
|
||||
* Can change vouchers
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
We currently see pretix' API as a beta-stage feature. We therefore do not give any guarantees
|
||||
for compatibility between feature releases of pretix (such as 1.5 and 1.6). However, as always,
|
||||
we try not to break things when we don't need to. Any backwards-incompatible changes will be
|
||||
prominently noted in the release notes.
|
||||
|
||||
We treat the following types of changes as *backwards-compatible* so we ask you to make sure
|
||||
that your clients can deal with them properly:
|
||||
|
||||
* Support of new API endpoints
|
||||
* Support of new HTTP methods for a given API endpoint
|
||||
* Support of new query parameters for a given API endpoint
|
||||
* New fields contained in API responses
|
||||
|
||||
We treat the following types of changes as *backwards-incompatible*:
|
||||
|
||||
* Type changes of fields in API responses
|
||||
* New required input fields for an API endpoint
|
||||
* New required type for input fields of an API endpoint
|
||||
* Removal of endpoints, API methods or fields
|
||||
|
||||
Pagination
|
||||
----------
|
||||
|
||||
Most lists of objects returned by pretix' API will be paginated. The response will take
|
||||
the form of:
|
||||
|
||||
.. sourcecode:: javascript
|
||||
|
||||
{
|
||||
"count": 117,
|
||||
"next": "https://pretix.eu/api/v1/organizers/?page=2",
|
||||
"previous": null,
|
||||
"results": […],
|
||||
}
|
||||
|
||||
As you can see, the response contains the total number of results in the field ``count``.
|
||||
The fields ``next`` and ``previous`` contain links to the next and previous page of results,
|
||||
respectively, or ``null`` if there is no such page. You can use those URLs to retrieve the
|
||||
respective page.
|
||||
|
||||
The field ``results`` contains a list of objects representing the first results. For most
|
||||
objects, every page contains 50 results.
|
||||
|
||||
Conditional fetching
|
||||
--------------------
|
||||
|
||||
If you pull object lists from pretix' APIs regularly, we ask you to implement conditional fetching
|
||||
to avoid unnecessary data traffic. This is not supported on all resources and we currently implement
|
||||
two different mechanisms for different resources, which is necessary because we can only obtain best
|
||||
efficiency for resources that do not support deletion operations.
|
||||
|
||||
Object-level conditional fetching
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The :ref:`rest-orders` resource list contains an HTTP header called ``X-Page-Generated`` containing the
|
||||
current time on the server in ISO 8601 format. On your next request, you can pass this header
|
||||
(as is, without any modifications necessary) as the ``modified_since`` query parameter and you will receive
|
||||
a list containing only objects that have changed in the time since your last request.
|
||||
|
||||
List-level conditional fetching
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If modification checks are not possible with this granularity, you can instead check for the full list.
|
||||
In this case, the list of objects may contain a regular HTTP header ``Last-Modified`` with the date of the
|
||||
last modification to any item of that resource. You can then pass this date back in your next request in the
|
||||
``If-Modified-Since`` header. If the any object has changed in the meantime, you will receive back a full list
|
||||
(if something it missing, this means the object has been deleted). If nothing happened, we'll send back a
|
||||
``304 Not Modified`` return code.
|
||||
|
||||
This is currently implemented on the following resources:
|
||||
|
||||
* :ref:`rest-categories`
|
||||
* :ref:`rest-items`
|
||||
* :ref:`rest-questions`
|
||||
* :ref:`rest-quotas`
|
||||
* :ref:`rest-subevents`
|
||||
* :ref:`rest-taxrules`
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
Error responses (of type 400-499) are returned in one of the following forms, depending on
|
||||
the type of error. General errors look like:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 405 Method Not Allowed
|
||||
Content-Type: application/json
|
||||
Content-Length: 42
|
||||
|
||||
{"detail": "Method 'DELETE' not allowed."}
|
||||
|
||||
Field specific input errors include the name of the offending fields as keys in the response:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
All structured API responses are returned in JSON format using standard JSON data types such
|
||||
as integers, floating point numbers, strings, lists, objects and booleans. Most fields can
|
||||
be ``null`` as well.
|
||||
|
||||
The following table shows some data types that have no native JSON representation and how
|
||||
we serialize them to JSON.
|
||||
|
||||
===================== ============================ ===================================
|
||||
Internal pretix type JSON representation Examples
|
||||
===================== ============================ ===================================
|
||||
Datetime String in ISO 8601 format ``"2017-12-27T10:00:00Z"``
|
||||
with timezone (normally UTC) ``"2017-12-27T10:00:00.596934Z"``,
|
||||
``"2017-12-27T10:00:00+02:00"``
|
||||
Date String in ISO 8601 format ``2017-12-27``
|
||||
Multi-lingual string Object of strings ``{"en": "red", "de": "rot", "de_Informal": "rot"}``
|
||||
Money String with decimal number ``"23.42"``
|
||||
Currency String with ISO 4217 code ``"EUR"``, ``"USD"``
|
||||
===================== ============================ ===================================
|
||||
|
||||
Query parameters
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Most list endpoints allow a filtering of the results using query parameters. In this case, booleans should be passed
|
||||
as the string values ``true`` and ``false``.
|
||||
|
||||
If the ``ordering`` parameter is documented for a resource, you can use it to sort the result set by one of the allowed
|
||||
fields. Prepend a ``-`` to the field name to reverse the sort order.
|
||||
|
||||
.. _CSRF policies: https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax
|
||||
BIN
doc/api/img/token_form.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
doc/api/img/token_success.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
18
doc/api/index.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
.. _`rest-api`:
|
||||
|
||||
REST API
|
||||
========
|
||||
|
||||
This part of the documentation contains information about the REST-style API
|
||||
exposed by pretix since version 1.5 that can be used by third-party programs
|
||||
to interact with pretix and its data structures.
|
||||
|
||||
Currently, the API provides mostly read-only capabilities, but it will be extended
|
||||
in functionality over time.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
fundamentals
|
||||
auth
|
||||
resources/index
|
||||
171
doc/api/oauth.rst
Normal file
@@ -0,0 +1,171 @@
|
||||
.. _`rest-oauth`:
|
||||
|
||||
OAuth authentication / "Connect with pretix"
|
||||
============================================
|
||||
|
||||
In addition to static tokens, pretix supports `OAuth2`_-based authentication starting with
|
||||
pretix 1.16. This allows you to put a "Connect with pretix" button into your website or tool
|
||||
that allows the user to easily set up a connection between the two systems.
|
||||
|
||||
If you haven't worked with OAuth before, have a look at the `OAuth2 Simplified`_ tutorial.
|
||||
|
||||
Registering an application
|
||||
--------------------------
|
||||
|
||||
To use OAuth, you need to register your application with the pretix instance you want to connect to.
|
||||
In order to do this, log in to your pretix account and go to your user settings. Click on "Authorized applications"
|
||||
first and then on "Manage your own apps". From there, you can "Create a new application".
|
||||
|
||||
You should fill in a descriptive name of your application that allows users to recognize who you are. You also need to
|
||||
give a list of fully-qualified URLs that users will be redirected to after a successful authorization. After you pressed
|
||||
"Save", you will be presented with a client ID and a client secret. Please note them down and treat the client secret
|
||||
like a password; it should not become available to your users.
|
||||
|
||||
Obtaining an authorization grant
|
||||
--------------------------------
|
||||
|
||||
To authorize a new user, link or redirect them to the ``authorize`` endpoint, passing your client ID as a query
|
||||
parameter. Additionally, you can pass a scope (currently either ``read``, ``write``, or ``read write``)
|
||||
and an URL the user should be redirected to after successful or failed authorization. You also need to pass the
|
||||
``response_type`` parameter with a value of ``code``. Example::
|
||||
|
||||
https://pretix.eu/api/v1/oauth/authorize?client_id=lsLi0hNL0vk53mEdYjNJxHUn1PcO1R6wVg81dLNT&response_type=code&scope=read+write&redirect_uri=https://pretalx.com
|
||||
|
||||
To prevent CSRF attacks, you can also optionally pass a ``state`` parameter with a random string. Later, when
|
||||
redirecting back to your application, we will pass the same ``state`` parameter back to you, so you can compare if they
|
||||
match.
|
||||
|
||||
After the user granted or denied access, they will be redirected back either to the ``redirect_url`` you passed in the
|
||||
query or to the first redirect URL configured in your application settings.
|
||||
|
||||
On successful registration, we will append the query parameter ``code`` to the URL containing an authorization code.
|
||||
For example, we might redirect the user to this URL::
|
||||
|
||||
https://pretalx.com/?code=eYBBf8gmeD4E01HLoj0XflqO4Lg3Cw&state=e3KCh9mfx07qxU4bRpXk
|
||||
|
||||
You will need this ``code`` parameter to perform the next step.
|
||||
|
||||
On a failed registration, a query string like ``?error=access_denied`` will be appended to the redirection URL.
|
||||
|
||||
.. note:: In this step, the user is allowed to restrict your access to certain organizer accounts. If you try to
|
||||
re-authenticate the user later, the user might be instantly redirected back to you if authorization is already
|
||||
given and would therefore be unable to review their organizer restriction settings. You can append the
|
||||
``approval_prompt=force`` query parameter if you want to make sure the user actively needs to confirm the
|
||||
authorization.
|
||||
|
||||
Getting an access token
|
||||
-----------------------
|
||||
|
||||
Using the ``code`` value you obtained above and your client ID, you can now request an access token that actually gives
|
||||
access to the API. The ``token`` endpoint expects you to authenticate using `HTTP Basic authentication`_ using your client
|
||||
ID as a username and your client secret as a password. You are also required to again supply the same ``redirect_uri``
|
||||
parameter that you used for the authorization.
|
||||
|
||||
.. http:get:: /api/v1/oauth/token
|
||||
|
||||
Request a new access token
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/oauth/token HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Authorization: Basic bHNMaTBoTkwwdms1M21FZFlqTkp4SFVuMVBjTzFSNndWZzgxZExOVDplSmpzZVA0UjJMN0hMcjBiS0p1b3BmbnJtT2cyY3NDeTdYaFVVZ0FoalhUU0NhZHhRTjk3cVNvMkpPaXlWTFpQOEozaTVQd1FVdFIwNUNycG5ac2Z0bXJjdmNTbkZ1SkFmb2ZsUTdZUDRpSjZNTWFYTHIwQ0FpNlhIRFJjV1Awcg==
|
||||
|
||||
grant_type=authorization_code&code=eYBBf8gmeD4E01HLoj0XflqO4Lg3Cw&redirect_uri=https://pretalx.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"access_token": "i3ytqTSRWsKp16fqjekHXa4tdM4qNC",
|
||||
"expires_in": 86400,
|
||||
"token_type": "Bearer",
|
||||
"scope": "read write",
|
||||
"refresh_token": "XBK0r8z4A4TTeR9LyMUyU2AM5rqpXp"
|
||||
}
|
||||
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
|
||||
As you can see, you receive two types of tokens: One "access token", and one "refresh token". The access token is valid
|
||||
for a day and can be used to actually access the API. The refresh token does not have an expiration date and can be used
|
||||
to obtain a new access_token after a day, so you should make sure to store the access token safely if you need long-term
|
||||
access.
|
||||
|
||||
Using the API with an access token
|
||||
----------------------------------
|
||||
|
||||
You can supply a valid access token as a ``Bearer``-type token in the ``Authorization`` header to get API access.
|
||||
|
||||
.. sourcecode:: http
|
||||
:emphasize-lines: 3
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Bearer i3ytqTSRWsKp16fqjekHXa4tdM4qNC
|
||||
|
||||
Refreshing an access token
|
||||
--------------------------
|
||||
|
||||
You can obtain a new access token using your refresh token any time. This can be done using the same ``token`` endpoint
|
||||
used to obtain the first access token above, but with a different set of parameters:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/oauth/token HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Authorization: Basic bHNMaTBoTkwwdms1M21FZFlqTkp4SFVuMVBjTzFSNndWZzgxZExOVDplSmpzZVA0UjJMN0hMcjBiS0p1b3BmbnJtT2cyY3NDeTdYaFVVZ0FoalhUU0NhZHhRTjk3cVNvMkpPaXlWTFpQOEozaTVQd1FVdFIwNUNycG5ac2Z0bXJjdmNTbkZ1SkFmb2ZsUTdZUDRpSjZNTWFYTHIwQ0FpNlhIRFJjV1Awcg==
|
||||
|
||||
grant_type=refresh_token&refresh_token=XBK0r8z4A4TTeR9LyMUyU2AM5rqpXp
|
||||
|
||||
The previous access token will instantly become invalid.
|
||||
|
||||
Revoking a token
|
||||
----------------
|
||||
|
||||
If you don't need a token any more or if you believe it may have been compromised, you can use the ``revoke_token``
|
||||
endpoint to revoke it.
|
||||
|
||||
.. http:get:: /api/v1/oauth/revoke_token
|
||||
|
||||
Revoke an access or refresh token. If you revoke an access token, you can still create a new one using the refresh token. If you
|
||||
revoke a refresh token, the connected access token will also be revoked.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/oauth/revoke_token HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Authorization: Basic bHNMaTBoTkwwdms1M21FZFlqTkp4SFVuMVBjTzFSNndWZzgxZExOVDplSmpzZVA0UjJMN0hMcjBiS0p1b3BmbnJtT2cyY3NDeTdYaFVVZ0FoalhUU0NhZHhRTjk3cVNvMkpPaXlWTFpQOEozaTVQd1FVdFIwNUNycG5ac2Z0bXJjdmNTbkZ1SkFmb2ZsUTdZUDRpSjZNTWFYTHIwQ0FpNlhIRFJjV1Awcg==
|
||||
|
||||
token=XBK0r8z4A4TTeR9LyMUyU2AM5rqpXp
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
If you want to revoke your client secret, you can generate a new one in the list of your managed applications in the
|
||||
pretix user interface.
|
||||
|
||||
.. _OAuth2: https://en.wikipedia.org/wiki/OAuth
|
||||
.. _OAuth2 Simplified: https://aaronparecki.com/oauth-2-simplified/
|
||||
.. _HTTP Basic authentication: https://en.wikipedia.org/wiki/Basic_access_authentication
|
||||
258
doc/api/resources/carts.rst
Normal file
@@ -0,0 +1,258 @@
|
||||
.. _rest-carts:
|
||||
|
||||
Cart positions
|
||||
==============
|
||||
|
||||
The API provides limited access to the cart position data model. This API currently only allows creating and deleting
|
||||
cart positions to reserve quota.
|
||||
|
||||
Cart position resource
|
||||
----------------------
|
||||
|
||||
The cart position resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the cart position
|
||||
cart_id string Identifier of the cart this belongs to. Needs to end
|
||||
in "@api" for API-created positions.
|
||||
datetime datetime Time of creation
|
||||
expires datetime The cart position will expire at this time and no longer block quota
|
||||
item integer ID of the item
|
||||
variation integer ID of the variation (or ``null``)
|
||||
price money (string) Price of this position
|
||||
attendee_name string Specified attendee name for this position (or ``null``)
|
||||
attendee_email string Specified attendee email address for this position (or ``null``)
|
||||
voucher integer Internal ID of the voucher used for this position (or ``null``)
|
||||
addon_to integer Internal ID of the position this position is an add-on for (or ``null``)
|
||||
subevent integer ID of the date inside an event series this position belongs to (or ``null``).
|
||||
answers list of objects Answers to user-defined questions
|
||||
├ question integer Internal ID of the answered question
|
||||
├ answer string Text representation of the answer
|
||||
├ question_identifier string The question's ``identifier`` field
|
||||
├ options list of integers Internal IDs of selected option(s)s (only for choice types)
|
||||
└ option_identifiers list of strings The ``identifier`` fields of the selected option(s)s
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.17
|
||||
|
||||
This resource has been added.
|
||||
|
||||
|
||||
Cart position endpoints
|
||||
-----------------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/cartpositions/
|
||||
|
||||
Returns a list of API-created cart positions.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/cartpositions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
X-Page-Generated: 2017-12-01T10:00:00Z
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"cart_id": "XwokV8FojQviD9jhtDzKvHFdlLRNMhlfo3cNjGbuK6MUTQDT@api",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": null,
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"datetime": "2018-06-11T10:00:00Z",
|
||||
"expires": "2018-06-11T10:00:00Z",
|
||||
"includes_tax": true,
|
||||
"answers": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/cartpositions/(id)/
|
||||
|
||||
Returns information on one cart position, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/cartpositions/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"cart_id": "XwokV8FojQviD9jhtDzKvHFdlLRNMhlfo3cNjGbuK6MUTQDT@api",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": null,
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"datetime": "2018-06-11T10:00:00Z",
|
||||
"expires": "2018-06-11T10:00:00Z",
|
||||
"includes_tax": true,
|
||||
"answers": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the position to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested cart position does not exist.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/cartpositions/
|
||||
|
||||
Creates a new cart position.
|
||||
|
||||
.. warning:: This endpoint is considered **experimental**. It might change at any time without prior notice.
|
||||
|
||||
.. warning::
|
||||
|
||||
This endpoint is intended for advanced users. It is not designed to be used to build your own shop frontend.
|
||||
There is a lot that it does not or can not do, and you will need to be careful using it.
|
||||
It allows to bypass many of the restrictions imposed when creating a cart through the
|
||||
regular shop.
|
||||
|
||||
Specifically, this endpoint currently
|
||||
|
||||
* does not validate if products are only to be sold in a specific time frame
|
||||
|
||||
* does not validate if the event's ticket sales are already over or haven't started
|
||||
|
||||
* does not support add-on products at the moment
|
||||
|
||||
* does not check or calculate prices but believes any prices you send
|
||||
|
||||
* does not support the redemption of vouchers
|
||||
|
||||
* does not prevent you from buying items that can only be bought with a voucher
|
||||
|
||||
* does not support file upload questions
|
||||
|
||||
You can supply the following fields of the resource:
|
||||
|
||||
* ``cart_id`` (optional, needs to end in ``@api``)
|
||||
* ``item``
|
||||
* ``variation`` (optional)
|
||||
* ``price``
|
||||
* ``attendee_name`` (optional)
|
||||
* ``attendee_email`` (optional)
|
||||
* ``subevent`` (optional)
|
||||
* ``expires`` (optional)
|
||||
* ``includes_tax`` (optional)
|
||||
* ``answers``
|
||||
|
||||
* ``question``
|
||||
* ``answer``
|
||||
* ``options``
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/cartpositions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"answers": [
|
||||
{
|
||||
"question": 1,
|
||||
"answer": "23",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
(Full cart position resource, see above.)
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create a position for
|
||||
:param event: The ``slug`` field of the event to create a position for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data or lack of quota.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this
|
||||
order.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/cartpositions/(id)/
|
||||
|
||||
Deletes a cart position, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/cartpositions/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the position to delete
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested cart position does not exist.
|
||||
239
doc/api/resources/categories.rst
Normal file
@@ -0,0 +1,239 @@
|
||||
.. _`rest-categories`:
|
||||
|
||||
Item categories
|
||||
===============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Categories provide grouping for items (better known as products).
|
||||
The category resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the category
|
||||
name multi-lingual string The category's visible name
|
||||
internal_name string An optional name that is only used in the backend
|
||||
description multi-lingual string A public description (might include markdown, can
|
||||
be ``null``)
|
||||
position integer An integer, used for sorting the categories
|
||||
is_addon boolean If ``True``, items within this category are not on sale
|
||||
on their own but the category provides a source for
|
||||
defining add-ons for other products.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.14
|
||||
|
||||
The operations POST, PATCH, PUT and DELETE have been added.
|
||||
|
||||
.. versionchanged:: 1.16
|
||||
|
||||
The field ``internal_name`` has been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/categories/
|
||||
|
||||
Returns a list of all categories within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/categories/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean is_addon: If set to ``true`` or ``false``, only categories with this value for the field ``is_addon`` will be
|
||||
returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/categories/(id)/
|
||||
|
||||
Returns information on one category, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/categories/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the category to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/categories/
|
||||
|
||||
Creates a new category
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/categories/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Tickets"},
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create a category for
|
||||
:param event: The ``slug`` field of the event to create a category for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The category could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/categories/(id)/
|
||||
|
||||
Update a category. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/categories/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"is_addon": true
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"internal_name": "",
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": true
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the category to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The category could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/category/(id)/
|
||||
|
||||
Delete a category.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/categories/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the category to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
630
doc/api/resources/checkinlists.rst
Normal file
@@ -0,0 +1,630 @@
|
||||
Check-in lists
|
||||
==============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
You can create check-in lists that you can use e.g. at the entrance of your event to track who is coming and if they
|
||||
actually bought a ticket.
|
||||
|
||||
You can create multiple check-in lists to separate multiple parts of your event, for example if you have separate
|
||||
entries for multiple ticket types. Different check-in lists are completely independent: If a ticket shows up on two
|
||||
lists, it is valid once on every list. This might be useful if you run a festival with festival passes that allow
|
||||
access to every or multiple performances as well as tickets only valid for single performances.
|
||||
|
||||
The check-in list resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the check-in list
|
||||
name string The internal name of the check-in list
|
||||
all_products boolean If ``true``, the check-in lists contains tickets of all products in this event. The ``limit_products`` field is ignored in this case.
|
||||
limit_products list of integers List of item IDs to include in this list.
|
||||
subevent integer ID of the date inside an event series this list belongs to (or ``null``).
|
||||
position_count integer Number of tickets that match this list (read-only).
|
||||
checkin_count integer Number of check-ins performed on this list (read-only).
|
||||
include_pending boolean If ``true``, the check-in list also contains tickets from orders in pending state.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.10
|
||||
|
||||
This resource has been added.
|
||||
|
||||
.. versionchanged:: 1.11
|
||||
|
||||
The ``positions`` endpoints have been added.
|
||||
|
||||
.. versionchanged:: 1.13
|
||||
|
||||
The ``include_pending`` field has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The ``../status/`` detail endpoint has been added.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/
|
||||
|
||||
Returns a list of all check-in lists within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkinlists/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Default list",
|
||||
"checkin_count": 123,
|
||||
"position_count": 456,
|
||||
"all_products": true,
|
||||
"limit_products": [],
|
||||
"include_pending": false,
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query integer subevent: Only return check-in lists of the sub-event with the given ID
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(id)/
|
||||
|
||||
Returns information on one check-in list, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Default list",
|
||||
"checkin_count": 123,
|
||||
"position_count": 456,
|
||||
"all_products": true,
|
||||
"limit_products": [],
|
||||
"include_pending": false,
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the check-in list to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(id)/status/
|
||||
|
||||
Returns detailed status information on a check-in list, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/status/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"checkin_count": 17,
|
||||
"position_count": 42,
|
||||
"event": {
|
||||
"name": "Demo Converence",
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"name": "T-Shirt",
|
||||
"id": 1,
|
||||
"checkin_count": 1,
|
||||
"admission": False,
|
||||
"position_count": 1,
|
||||
"variations": [
|
||||
{
|
||||
"value": "Red",
|
||||
"id": 1,
|
||||
"checkin_count": 1,
|
||||
"position_count": 12
|
||||
},
|
||||
{
|
||||
"value": "Blue",
|
||||
"id": 2,
|
||||
"checkin_count": 4,
|
||||
"position_count": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Ticket",
|
||||
"id": 2,
|
||||
"checkin_count": 15,
|
||||
"admission": True,
|
||||
"position_count": 22,
|
||||
"variations": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the check-in list to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/
|
||||
|
||||
Creates a new check-in list.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/checkinlists/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"name": "VIP entry",
|
||||
"all_products": false,
|
||||
"limit_products": [1, 2],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "VIP entry",
|
||||
"checkin_count": 0,
|
||||
"position_count": 0,
|
||||
"all_products": false,
|
||||
"limit_products": [1, 2],
|
||||
"include_pending": false,
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a list for
|
||||
:param event: The ``slug`` field of the event to create a list for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The list could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(id)/
|
||||
|
||||
Update a check-in list. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field and the ``checkin_count`` and ``position_count``
|
||||
fields.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"name": "Backstage",
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Backstage",
|
||||
"checkin_count": 23,
|
||||
"position_count": 42,
|
||||
"all_products": false,
|
||||
"limit_products": [1, 2],
|
||||
"include_pending": false,
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the list to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The list could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/checkinlist/(id)/
|
||||
|
||||
Delete a check-in list. Note that this also deletes the information on all check-ins performed via this list.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/checkinlist/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the check-in list to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
|
||||
Order position endpoints
|
||||
------------------------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The order positions endpoint has been extended by the filter queries ``item__in``, ``variation__in``,
|
||||
``order__status__in``, ``subevent__in``, ``addon_to__in``, and ``search``. The search for attendee names and order
|
||||
codes is now case-insensitive.
|
||||
|
||||
The ``.../redeem/`` endpoint has been added.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
|
||||
The order positions endpoint has been extended by the filter queries ``voucher`` and ``voucher__code``.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/
|
||||
|
||||
Returns a list of all order positions within a given event. The result is the same as
|
||||
the :ref:`order-position-resource`, with one important difference: the ``checkins`` value will only include
|
||||
check-ins for the selected list.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/positions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"pseudonymization_id": "MQLJvANO3B",
|
||||
"checkins": [
|
||||
{
|
||||
"list": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``order__code``,
|
||||
``order__datetime``, ``positionid``, ``attendee_name``, ``last_checked_in`` and ``order__email``. Default:
|
||||
``attendee_name,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query string search: Fuzzy search matching the attendee name, order code, invoice address name as well as to the beginning of the secret.
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer item__in: Only return positions with the purchased item matching one of the given comma-separated IDs.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
:query integer variation__in: Only return positions with one of the purchased item variation matching the given
|
||||
comma-separated IDs.
|
||||
:query string attendee_name: Only return positions with the given value in the attendee_name field. Also, add-on
|
||||
products positions are shown if they refer to an attendee with the given name.
|
||||
:query string secret: Only return positions with the given ticket secret.
|
||||
:query string order__status: Only return positions with the given order status.
|
||||
:query string order__status__in: Only return positions with one the given comma-separated order status.
|
||||
:query boolean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
checked in already.
|
||||
:query integer subevent: Only return positions of the sub-event with the given ID
|
||||
:query integer subevent__in: Only return positions of one of the sub-events with the given comma-separated IDs
|
||||
:query integer addon_to: Only return positions that are add-ons to the position with the given ID.
|
||||
:query integer addon_to__in: Only return positions that are add-ons to one of the positions with the given
|
||||
comma-separated IDs.
|
||||
:query string voucher: Only return positions with a specific voucher.
|
||||
:query string voucher__code: Only return positions with a specific voucher code.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param list: The ID of the check-in list to look for
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 404: The requested check-in list does not exist.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/checkinlists/(list)/positions/(id)/
|
||||
|
||||
Returns information on one order position, identified by its internal ID.
|
||||
The result format is the same as the :ref:`order-position-resource`, with one important difference: the
|
||||
``checkins`` value will only include check-ins for the selected list.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/positions/23442/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": null,
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"pseudonymization_id": "MQLJvANO3B",
|
||||
"checkins": [
|
||||
{
|
||||
"list": 1,
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param list: The ID of the check-in list to look for
|
||||
:param id: The ``id`` field of the order position to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
: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.
|
||||
|
||||
.. 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
|
||||
accepts a number of optional requests in the body.
|
||||
|
||||
:<json boolean questions_supported: When this parameter is set to ``true``, handling of questions is supported. If
|
||||
you do not implement question handling in your user interface, you **must**
|
||||
set this to ``false``. In that case, questions will just be ignored. Defaults
|
||||
to ``true``.
|
||||
:<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 previous check-ins or required
|
||||
questions that have not been filled. Defaults to ``false``.
|
||||
:<json boolean ignore_unpaid: Specifies that the check-in should succeed even if the order is in pending state.
|
||||
Defaults to ``false``.
|
||||
:<json string nonce: You can set this parameter to a unique random value to identify this check-in. If you're sending
|
||||
this request twice with the same nonce, the second request will also succeed but will always
|
||||
create only one check-in object even when the previous request was successful as well. This
|
||||
allows for a certain level of idempotency and enables you to re-try after a connection failure.
|
||||
:<json object answers: If questions are supported/required, you may/must supply a mapping of question IDs to their
|
||||
respective answers. The answers should always be strings. In case of (multiple-)choice-type
|
||||
answers, the string should contain the (comma-separated) IDs of the selected options.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/checkinlists/1/positions/234/redeem/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
{
|
||||
"force": false,
|
||||
"ignore_unpaid": false,
|
||||
"nonce": "Pvrk50vUzQd0DhdpNRL4I4OcXsvg70uA",
|
||||
"datetime": null,
|
||||
"questions_supported": true,
|
||||
"answers": {
|
||||
"4": "XS"
|
||||
}
|
||||
}
|
||||
|
||||
**Example successful response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "ok"
|
||||
}
|
||||
|
||||
**Example response with required questions**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
Content-Type: text/json
|
||||
|
||||
{
|
||||
"status": "incomplete"
|
||||
"questions": [
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": true,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example error response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/json
|
||||
|
||||
{
|
||||
"status": "error",
|
||||
"reason": "unpaid",
|
||||
}
|
||||
|
||||
Possible error reasons:
|
||||
|
||||
* ``unpaid`` - Ticket is not paid for or has been refunded
|
||||
* ``already_redeemed`` - Ticket already has been redeemed
|
||||
* ``product`` - Tickets with this product may not be scanned at this device
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param list: The ID of the check-in list to look for
|
||||
:param id: The ``id`` field of the order position to fetch
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: Invalid or incomplete request, see above
|
||||
:statuscode 401: Authentication failure
|
||||
: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.
|
||||
401
doc/api/resources/events.rst
Normal file
@@ -0,0 +1,401 @@
|
||||
Events
|
||||
======
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The event resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
name multi-lingual string The event's full name
|
||||
slug string A short form of the name, used e.g. in URLs.
|
||||
live boolean If ``true``, the event ticket shop is publicly
|
||||
available.
|
||||
currency string The currency this event is handled in.
|
||||
date_from datetime The event's start date
|
||||
date_to datetime The event's end date (or ``null``)
|
||||
date_admission datetime The event's admission date (or ``null``)
|
||||
is_public boolean If ``true``, the event shows up in places like the
|
||||
organizer's public list of events
|
||||
presale_start datetime The date at which the ticket shop opens (or ``null``)
|
||||
presale_end datetime The date at which the ticket shop closes (or ``null``)
|
||||
location multi-lingual string The event location (or ``null``)
|
||||
has_subevents boolean ``True`` if the event series feature is active for this
|
||||
event. Cannot change after event is created.
|
||||
meta_data dict Values set for organizer-specific meta data parameters.
|
||||
plugins list A list of package names of the enabled plugins for this
|
||||
event.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
The ``meta_data`` field has been added.
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The ``plugins`` field has been added.
|
||||
The operations POST, PATCH, PUT and DELETE have been added.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
|
||||
Filters have been added to the list of events.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/
|
||||
|
||||
Returns a list of all events within a given organizer the authenticated user/token has access to.
|
||||
|
||||
Permission required: "Can change event settings"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
"pretix.plugins.paypal"
|
||||
"pretix.plugins.ticketoutputpdf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query is_public: If set to ``true``/``false``, only events with a matching value of ``is_public`` are returned.
|
||||
:query live: If set to ``true``/``false``, only events with a matching value of ``live`` are returned.
|
||||
:query has_subevents: If set to ``true``/``false``, only events with a matching value of ``has_subevents`` are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned. Event series are never (always) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned. Event series are never (always) returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned. Event series are never returned.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/
|
||||
|
||||
Returns information on one event, identified by its slug.
|
||||
|
||||
Permission required: "Can change event settings"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer"
|
||||
"pretix.plugins.stripe"
|
||||
"pretix.plugins.paypal"
|
||||
"pretix.plugins.ticketoutputpdf"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/
|
||||
|
||||
Creates a new event
|
||||
|
||||
Please note that events cannot be created as 'live' using this endpoint. Quotas and payment must be added to the
|
||||
event before sales can go live.
|
||||
|
||||
Permission required: "Can create events"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create.
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The event could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/clone/
|
||||
|
||||
Creates a new event with properties as set in the request body. The properties that are copied are: 'is_public',
|
||||
settings, plugin settings, items, variations, add-ons, quotas, categories, tax rules, questions.
|
||||
|
||||
If the 'plugins' and/or 'is_public' fields are present in the post body this will determine their value. Otherwise
|
||||
their value will be copied from the existing event.
|
||||
|
||||
Please note that you can only copy from events under the same organizer.
|
||||
|
||||
Permission required: "Can create events"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/clone/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create.
|
||||
:param event: The ``slug`` field of the event to copy settings and items from.
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The event could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to create this resource.
|
||||
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/
|
||||
|
||||
Updates an event
|
||||
|
||||
Permission required: "Can change event settings"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer",
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.pretixdroid"
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false,
|
||||
"meta_data": {},
|
||||
"plugins": [
|
||||
"pretix.plugins.banktransfer",
|
||||
"pretix.plugins.stripe",
|
||||
"pretix.plugins.paypal",
|
||||
"pretix.plugins.pretixdroid"
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to update
|
||||
:param event: The ``slug`` field of the event to update
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The event could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/
|
||||
|
||||
Delete an event. Note that events with orders cannot be deleted to ensure data integrity.
|
||||
|
||||
Permission required: "Can change event settings"
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
23
doc/api/resources/index.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
Resources and endpoints
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
organizers
|
||||
events
|
||||
subevents
|
||||
taxrules
|
||||
categories
|
||||
items
|
||||
item_variations
|
||||
item_add-ons
|
||||
questions
|
||||
question_options
|
||||
quotas
|
||||
orders
|
||||
invoices
|
||||
vouchers
|
||||
checkinlists
|
||||
waitinglist
|
||||
carts
|
||||
281
doc/api/resources/invoices.rst
Normal file
@@ -0,0 +1,281 @@
|
||||
Invoices
|
||||
========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The invoice resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
number string Invoice number (with prefix)
|
||||
order string Order code of the order this invoice belongs to
|
||||
is_cancellation boolean ``True``, if this invoice is the cancellation of a
|
||||
different invoice.
|
||||
invoice_from string Sender address
|
||||
invoice_to string Receiver address
|
||||
date date Invoice date
|
||||
refers string Invoice number of an invoice this invoice refers to
|
||||
(for example a cancellation refers to the invoice it
|
||||
cancels) or ``null``.
|
||||
locale string Invoice locale
|
||||
introductory_text string Text to be printed above the product list
|
||||
additional_text string Text to be printed below the product list
|
||||
payment_provider_text string Text to be printed below the product list with
|
||||
payment information
|
||||
footer_text string Text to be printed in the page footer area
|
||||
lines list of objects The actual invoice contents
|
||||
├ description string Text representing the invoice line (e.g. product name)
|
||||
├ gross_value money (string) Price including taxes
|
||||
├ tax_value money (string) Tax amount included
|
||||
├ tax_name string Name of used tax rate (e.g. "VAT")
|
||||
└ tax_rate decimal (string) Used tax rate
|
||||
foreign_currency_display string If the invoice should also show the total and tax
|
||||
amount in a different currency, this contains the
|
||||
currency code (``null`` otherwise).
|
||||
foreign_currency_rate decimal (string) If ``foreign_currency_rate`` is set and the system
|
||||
knows the exchange rate to the event currency at
|
||||
invoicing time, it is stored here.
|
||||
foreign_currency_rate_date date If ``foreign_currency_rate`` is set, this signifies the
|
||||
date at which the currency rate was obtained.
|
||||
internal_reference string Customer's reference to be printed on the invoice.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
|
||||
The attribute ``invoice_no`` has been dropped in favor of ``number`` which includes the number including the prefix,
|
||||
since the prefix can now vary. Also, invoices now need to be identified by their ``number`` instead of the raw
|
||||
number.
|
||||
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
The attributes ``lines.tax_name``, ``foreign_currency_display``, ``foreign_currency_rate``, and
|
||||
``foreign_currency_rate_date`` have been added.
|
||||
|
||||
|
||||
.. versionchanged:: 1.9
|
||||
|
||||
The attribute ``internal_reference`` has been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/
|
||||
|
||||
Returns a list of all invoices within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from": "Big Events LLC\nDemo street 12\nDemo town",
|
||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT ID: EU123456789",
|
||||
"date": "2017-12-01",
|
||||
"refers": null,
|
||||
"locale": "en",
|
||||
"introductory_text": "thank you for your purchase of the following items:",
|
||||
"internal_reference": "",
|
||||
"additional_text": "We are looking forward to see you on our conference!",
|
||||
"payment_provider_text": "Please transfer the money to our account ABC…",
|
||||
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
|
||||
"lines": [
|
||||
{
|
||||
"description": "Budget Ticket",
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_name": "VAT",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
],
|
||||
"foreign_currency_display": "PLN",
|
||||
"foreign_currency_rate": "4.2408",
|
||||
"foreign_currency_rate_date": "2017-07-24"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean is_cancellation: If set to ``true`` or ``false``, only invoices with this value for the field
|
||||
``is_cancellation`` will be returned.
|
||||
:query string order: If set, only invoices belonging to the order with the given order code will be returned.
|
||||
:query string refers: If set, only invoices referring to the given invoice will be returned.
|
||||
:query string locale: If set, only invoices with the given locale will be returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date`` and
|
||||
``nr`` (equals to ``number``). Default: ``nr``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/
|
||||
|
||||
Returns information on one invoice, identified by its invoice number.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/SAMPLECONF-00001/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from": "Big Events LLC\nDemo street 12\nDemo town",
|
||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT ID: EU123456789",
|
||||
"date": "2017-12-01",
|
||||
"refers": null,
|
||||
"locale": "en",
|
||||
"introductory_text": "thank you for your purchase of the following items:",
|
||||
"internal_reference": "",
|
||||
"additional_text": "We are looking forward to see you on our conference!",
|
||||
"payment_provider_text": "Please transfer the money to our account ABC…",
|
||||
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
|
||||
"lines": [
|
||||
{
|
||||
"description": "Budget Ticket",
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_name": "VAT",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
],
|
||||
"foreign_currency_display": "PLN",
|
||||
"foreign_currency_rate": "4.2408",
|
||||
"foreign_currency_rate_date": "2017-07-24"
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/download/
|
||||
|
||||
Download an invoice in PDF format.
|
||||
|
||||
Note that in some cases the PDF file might not yet have been created. In that case, you will receive a status
|
||||
code :http:statuscode:`409` and you are expected to retry the request after a short period of waiting.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/download/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
...
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting for a few
|
||||
seconds.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/reissue/
|
||||
|
||||
Cancels the invoice and creates a new one.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/reissue/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to reissue
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The invoice has already been canceled
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/regenerate/
|
||||
|
||||
Re-generates the invoice from order data.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/regenerate/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to regenerate
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The invoice has already been canceled
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
246
doc/api/resources/item_add-ons.rst
Normal file
@@ -0,0 +1,246 @@
|
||||
Item add-ons
|
||||
============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
With add-ons, you can specify products that can be bought as an addition to this specific product. For example, if you
|
||||
host a conference with a base conference ticket and a number of workshops, you could define the workshops as add-ons to
|
||||
the conference ticket. With this configuration, the workshops cannot be bought on their own but only in combination with
|
||||
a conference ticket. You can here specify categories of products that can be used as add-ons to this product. You can
|
||||
also specify the minimum and maximum number of add-ons of the given category that can or need to be chosen. The user can
|
||||
buy every add-on from the category at most once. If an add-on product has multiple variations, only one of them can be
|
||||
bought.
|
||||
The add-ons resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the add-on
|
||||
addon_category integer Internal ID of the item category the add-on can be
|
||||
chosen from.
|
||||
min_count integer The minimal number of add-ons that need to be chosen.
|
||||
max_count integer The maximal number of add-ons that can be chosen.
|
||||
position integer An integer, used for sorting
|
||||
price_included boolean Adding this add-on to the item is free
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.12
|
||||
|
||||
This resource has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/addons/
|
||||
|
||||
Returns a list of all add-ons for a given item.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/11/addons/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 3,
|
||||
"addon_category": 1,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 0,
|
||||
"price_included": true
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"addon_category": 2,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 1,
|
||||
"price_included": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param item: The ``id`` field of the item to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/item does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/addons/(id)/
|
||||
|
||||
Returns information on one add-on, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/addons/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 3,
|
||||
"addon_category": 1,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 1,
|
||||
"price_included": true
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param item: The ``id`` field of the item to fetch
|
||||
:param id: The ``id`` field of the add-on to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/bigevents/events/sampleconf/items/1/addons/
|
||||
|
||||
Creates a new add-on
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/(organizer)/events/(event)/items/(item)/addons/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"addon_category": 1,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 1,
|
||||
"price_included": true
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 3,
|
||||
"addon_category": 1,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 1,
|
||||
"price_included": true
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a add-on for
|
||||
:param event: The ``slug`` field of the event to create a add-on for
|
||||
:param item: The ``id`` field of the item to create a add-on for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The add-on could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/addon/(id)/
|
||||
|
||||
Update an add-on. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/addons/3/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 3,
|
||||
"addon_category": 1,
|
||||
"min_count": 0,
|
||||
"max_count": 10,
|
||||
"position": 1,
|
||||
"price_included": true
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param item: The ``id`` field of the item to modify
|
||||
:param id: The ``id`` field of the add-on to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The add-on could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/addons/(id)/
|
||||
|
||||
Delete an add-on.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/addons/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to modify
|
||||
:param id: The ``id`` field of the add-on to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
258
doc/api/resources/item_variations.rst
Normal file
@@ -0,0 +1,258 @@
|
||||
Item variations
|
||||
===============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Variations of items can be use for products (items) that are available in different sizes, colors or other variations
|
||||
of the same product.
|
||||
The variations resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the variation
|
||||
default_price money (string) The price set directly for this variation or ``null``
|
||||
price money (string) The price used for this variation. This is either the
|
||||
same as ``default_price`` if that value is set or equal
|
||||
to the item's ``default_price`` (read-only).
|
||||
active boolean If ``False``, this variation will not be sold or shown.
|
||||
description multi-lingual string A public description of the variation. May contain
|
||||
Markdown syntax or can be ``null``.
|
||||
position integer An integer, used for sorting
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.12
|
||||
|
||||
This resource has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/variations/
|
||||
|
||||
Returns a list of all variations for a given item.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/11/variations/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"value": {
|
||||
"en": "S"
|
||||
},
|
||||
"active": true,
|
||||
"description": {
|
||||
"en": "Test2"
|
||||
},
|
||||
"position": 0,
|
||||
"default_price": "223.00",
|
||||
"price": 223.0
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"value": {
|
||||
"en": "L"
|
||||
},
|
||||
"active": true,
|
||||
"description": {},
|
||||
"position": 1,
|
||||
"default_price": null,
|
||||
"price": 15.0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
|
||||
returned.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param item: The ``id`` field of the item to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/item does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/variations/(id)/
|
||||
|
||||
Returns information on one variation, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/variations/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 3,
|
||||
"value": {
|
||||
"en": "Student"
|
||||
},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param item: The ``id`` field of the item to fetch
|
||||
:param id: The ``id`` field of the variation to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/variations/
|
||||
|
||||
Creates a new variation
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/items/1/variations/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a variation for
|
||||
:param event: The ``slug`` field of the event to create a variation for
|
||||
:param item: The ``id`` field of the item to create a variation for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The variation could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/items/(item)/variations/(id)/
|
||||
|
||||
Update a variation. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` and the ``price`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/variations/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"active": false,
|
||||
"position": 1
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": false,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to modify
|
||||
:param id: The ``id`` field of the variation to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The variation could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/variations/(id)/
|
||||
|
||||
Delete a variation.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/variations/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to modify
|
||||
:param id: The ``id`` field of the variation to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
514
doc/api/resources/items.rst
Normal file
@@ -0,0 +1,514 @@
|
||||
.. _rest-items:
|
||||
|
||||
Items
|
||||
=====
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Items (better known as products) are the things that can be sold using pretix.
|
||||
The item resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the item
|
||||
name multi-lingual string The item's visible name
|
||||
internal_name string An optional name that is only used in the backend
|
||||
default_price money (string) The item price that is applied if the price is not
|
||||
overwritten by variations or other options.
|
||||
category integer The ID of the category this item belongs to
|
||||
(or ``null``).
|
||||
active boolean If ``False``, the item is hidden from all public lists
|
||||
and will not be sold.
|
||||
description multi-lingual string A public description of the item. May contain Markdown
|
||||
syntax or can be ``null``.
|
||||
free_price boolean If ``True``, customers can change the price at which
|
||||
they buy the product (however, the price can't be set
|
||||
lower than the price defined by ``default_price`` or
|
||||
otherwise).
|
||||
tax_rate decimal (string) The VAT rate to be applied for this item.
|
||||
tax_rule integer The internal ID of the applied tax rule (or ``null``).
|
||||
admission boolean ``True`` for items that grant admission to the event
|
||||
(such as primary tickets) and ``False`` for others
|
||||
(such as add-ons or merchandise).
|
||||
position integer An integer, used for sorting
|
||||
picture string A product picture to be displayed in the shop
|
||||
(read-only).
|
||||
available_from datetime The first date time at which this item can be bought
|
||||
(or ``null``).
|
||||
available_until datetime The last date time at which this item can be bought
|
||||
(or ``null``).
|
||||
require_voucher boolean If ``True``, this item can only be bought using a
|
||||
voucher that is specifically assigned to this item.
|
||||
hide_without_voucher boolean If ``True``, this item is only shown during the voucher
|
||||
redemption process, but not in the normal shop
|
||||
frontend.
|
||||
allow_cancel boolean If ``False``, customers cannot cancel orders containing
|
||||
this item.
|
||||
min_per_order integer This product can only be bought if it is included at
|
||||
least this many times in the order (or ``null`` for no
|
||||
limitation).
|
||||
max_per_order integer This product can only be bought if it is included at
|
||||
most this many times in the order (or ``null`` for no
|
||||
limitation).
|
||||
checkin_attention boolean If ``True``, the check-in app should show a warning
|
||||
that this ticket requires special attention if such
|
||||
a product is being scanned.
|
||||
original_price money (string) An original price, shown for comparison, not used
|
||||
for price calculations.
|
||||
require_approval boolean If ``True``, orders with this product will need to be
|
||||
approved by the event organizer before they can be
|
||||
paid.
|
||||
has_variations boolean Shows whether or not this item has variations.
|
||||
variations list of objects A list with one object for each variation of this item.
|
||||
Can be empty. Only writable during creation,
|
||||
use separate endpoint to modify this later.
|
||||
├ id integer Internal ID of the variation
|
||||
├ value multi-lingual string The "name" of the variation
|
||||
├ default_price money (string) The price set directly for this variation or ``null``
|
||||
├ price money (string) The price used for this variation. This is either the
|
||||
same as ``default_price`` if that value is set or equal
|
||||
to the item's ``default_price``.
|
||||
├ active boolean If ``False``, this variation will not be sold or shown.
|
||||
├ description multi-lingual string A public description of the variation. May contain
|
||||
Markdown syntax or can be ``null``.
|
||||
└ position integer An integer, used for sorting
|
||||
addons list of objects Definition of add-ons that can be chosen for this item.
|
||||
Only writable during creation,
|
||||
use separate endpoint to modify this later.
|
||||
├ addon_category integer Internal ID of the item category the add-on can be
|
||||
chosen from.
|
||||
├ min_count integer The minimal number of add-ons that need to be chosen.
|
||||
├ max_count integer The maximal number of add-ons that can be chosen.
|
||||
└ position integer An integer, used for sorting
|
||||
└ price_included boolean Adding this add-on to the item is free
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
The attribute ``tax_rule`` has been added. ``tax_rate`` is kept for compatibility. The attribute
|
||||
``checkin_attention`` has been added.
|
||||
|
||||
.. versionchanged:: 1.12
|
||||
|
||||
The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added.
|
||||
The attribute ``price_included`` has been added to ``addons``.
|
||||
|
||||
.. versionchanged:: 1.16
|
||||
|
||||
The ``internal_name`` and ``original_price`` fields have been added.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
|
||||
The field ``require_approval`` has been added.
|
||||
|
||||
Notes
|
||||
-----
|
||||
Please note that an item either always has variations or never has. Once created with variations the item can never
|
||||
change to an item without and vice versa. To create an item with variations ensure that you POST an item with at least
|
||||
one variation.
|
||||
|
||||
Also note that ``variations`` and ``addons`` are only supported on ``POST``. To update/delete variations and add-ons please
|
||||
use the dedicated nested endpoints. By design this endpoint does not support ``PATCH`` and ``PUT`` with nested
|
||||
``variations`` and/or ``addons``.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/
|
||||
|
||||
Returns a list of all items within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"has_variations": false,
|
||||
"require_approval": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
|
||||
returned.
|
||||
:query integer category: If set to the ID of a category, only items within that category will be returned.
|
||||
:query boolean admission: If set to ``true`` or ``false``, only items with this value for the field ``admission``
|
||||
will be returned.
|
||||
:query string tax_rate: If set to a decimal value, only items with this tax rate will be returned.
|
||||
:query boolean free_price: If set to ``true`` or ``false``, only items with this value for the field ``free_price``
|
||||
will be returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/
|
||||
|
||||
Returns information on one item, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"has_variations": false,
|
||||
"require_approval": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the item to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/items/
|
||||
|
||||
Creates a new item
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/items/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"require_approval": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"internal_name": "",
|
||||
"default_price": "23.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"has_variations": true,
|
||||
"require_approval": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||
:param event: The ``slug`` field of the event to create an item for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/
|
||||
|
||||
Update an item. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``has_variations``, ``variations`` and the ``addon`` field. If
|
||||
you need to update/delete variations or add-ons please use the nested dedicated endpoints.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"name": {"en": "Ticket"},
|
||||
"default_price": "25.00"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Ticket"},
|
||||
"internal_name": "",
|
||||
"default_price": "25.00",
|
||||
"original_price": null,
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"tax_rule": 1,
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"checkin_attention": false,
|
||||
"has_variations": true,
|
||||
"require_approval": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The item could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/
|
||||
|
||||
Delete an item.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
1762
doc/api/resources/orders.rst
Normal file
90
doc/api/resources/organizers.rst
Normal file
@@ -0,0 +1,90 @@
|
||||
Organizers
|
||||
==========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
An organizers is an entity running any number of events. In pretix, every event belongs to one
|
||||
organizer and various settings, such as teams and permissions, are managed on organizer level.
|
||||
|
||||
The organizer resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
name string The organizer's full name, i.e. the name of an
|
||||
organization or company.
|
||||
slug string A short form of the name, used e.g. in URLs.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/
|
||||
|
||||
Returns a list of all organizers the authenticated user/token has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"name": "Big Events LLC",
|
||||
"slug": "Big Events",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/
|
||||
|
||||
Returns information on one organizer account, identified by its slug.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "Big Events LLC",
|
||||
"slug": "Big Events",
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
233
doc/api/resources/question_options.rst
Normal file
@@ -0,0 +1,233 @@
|
||||
Question options
|
||||
================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Questions of type "choice" or "multiple choice" can have different options attached.
|
||||
The options resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the option
|
||||
position integer An integer, used for sorting
|
||||
identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
answer multi-lingual string The displayed value of this option
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.12
|
||||
|
||||
This resource has been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/
|
||||
|
||||
Returns a list of all options for a given question.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/11/options/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 2,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only questions with this value for the field ``active`` will be
|
||||
returned.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param question: The ``id`` field of the question to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/question does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/(id)/
|
||||
|
||||
Returns information on one option, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param question: The ``id`` field of the question to fetch
|
||||
:param id: The ``id`` field of the option to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/
|
||||
|
||||
Creates a new option
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/question to create a option for
|
||||
:param event: The ``slug`` field of the event to create a option for
|
||||
:param question: The ``id`` field of the question to create a option for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The option could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/questions/(question)/options/(id)/
|
||||
|
||||
Update an option. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"position": 3
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:param id: The ``id`` field of the option to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The option could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/options/(id)/
|
||||
|
||||
Delete an option.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/questions/1/options/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:param id: The ``id`` field of the option to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
371
doc/api/resources/questions.rst
Normal file
@@ -0,0 +1,371 @@
|
||||
.. spelling:: checkin
|
||||
|
||||
.. _rest-questions:
|
||||
|
||||
Questions
|
||||
=========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Questions define additional fields that need to be filled out by customers during checkout.
|
||||
The question resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the question
|
||||
question multi-lingual string The field label shown to the customer
|
||||
type string The expected type of answer. Valid options:
|
||||
|
||||
* ``N`` – number
|
||||
* ``S`` – one-line string
|
||||
* ``T`` – multi-line string
|
||||
* ``B`` – boolean
|
||||
* ``C`` – choice from a list
|
||||
* ``M`` – multiple choice from a list
|
||||
* ``F`` – file upload
|
||||
* ``D`` – date
|
||||
* ``H`` – time
|
||||
* ``W`` – date and time
|
||||
required boolean If ``True``, the question needs to be filled out.
|
||||
position integer An integer, used for sorting
|
||||
items list of integers List of item IDs this question is assigned to.
|
||||
identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
ask_during_checkin boolean If ``True``, this question will not be asked while
|
||||
buying the ticket, but will show up when redeeming
|
||||
the ticket instead.
|
||||
options list of objects In case of question type ``C`` or ``M``, this lists the
|
||||
available objects. Only writable during creation,
|
||||
use separate endpoint to modify this later.
|
||||
├ id integer Internal ID of the option
|
||||
├ position integer An integer, used for sorting
|
||||
├ identifier string An arbitrary string that can be used for matching with
|
||||
other sources.
|
||||
└ answer multi-lingual string The displayed value of this option
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.12
|
||||
|
||||
The values ``D``, ``H``, and ``W`` for the field ``type`` are now allowed and the ``ask_during_checkin`` field has
|
||||
been added.
|
||||
|
||||
.. versionchanged:: 1.14
|
||||
|
||||
Write methods have been added. The attribute ``identifier`` has been added to both the resource itself and the
|
||||
options resource. The ``position`` attribute has been added to the options resource.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The questions endpoint has been extended by the filter queries ``ask_during_checkin``, ``requred``, and
|
||||
``identifier``.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/
|
||||
|
||||
Returns a list of all questions within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 0,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 1,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 2,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:query string identifier: Only return questions with the given identifier string
|
||||
:query boolean ask_during_checkin: Only return questions that are or are not to be asked during check-in
|
||||
:query boolean required: Only return questions that are or are not required to fill in
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
Returns information on one question, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the question to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/questions/
|
||||
|
||||
Creates a new question
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/questions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"ask_during_checkin": false,
|
||||
"options": [
|
||||
{
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event to create an item for
|
||||
:param event: The ``slug`` field of the event to create an item for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The item could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
Update a question. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``options`` field. If
|
||||
you need to update/delete options please use the nested dedicated endpoints.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"position": 2
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 2,
|
||||
"identifier": "WY3TP9SL",
|
||||
"ask_during_checkin": false,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"identifier": "LVETRWVU",
|
||||
"position": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"identifier": "DFEMJWMJ",
|
||||
"position": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"identifier": "W9AH7RDE",
|
||||
"position": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the question to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The item could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
Delete a question.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the item to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
278
doc/api/resources/quotas.rst
Normal file
@@ -0,0 +1,278 @@
|
||||
.. _rest-quotas:
|
||||
|
||||
Quotas
|
||||
======
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Quotas define how many times an item can be sold.
|
||||
The quota resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the quota
|
||||
name string The internal name of the quota
|
||||
size integer The size of the quota or ``null`` for unlimited
|
||||
items list of integers List of item IDs this quota acts on.
|
||||
variations list of integers List of item variation IDs this quota acts on.
|
||||
subevent integer ID of the date inside an event series this quota belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.10
|
||||
|
||||
The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/
|
||||
|
||||
Returns a list of all quotas within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:query integer subevent: Only return quotas of the sub-event with the given ID
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/
|
||||
|
||||
Returns information on one quota, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the quota to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/quotas/
|
||||
|
||||
Creates a new quota
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/quotas/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content: application/json
|
||||
|
||||
{
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer of the event/item to create a quota for
|
||||
:param event: The ``slug`` field of the event to create a quota for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The quota could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/
|
||||
|
||||
Update a quota. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` field.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/quotas/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{
|
||||
"name": "New Ticket Quota",
|
||||
"size": 100,
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 2,
|
||||
"name": "New Ticket Quota",
|
||||
"size": 100,
|
||||
"items": [
|
||||
1,
|
||||
2
|
||||
],
|
||||
"variations": [
|
||||
1,
|
||||
2
|
||||
],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the quota rule to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The quota could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/quota/(id)/
|
||||
|
||||
Delete a quota. Note that if you delete a quota the items the quota acts on might no longer be available for sale.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/quotas/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the quotas to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/availability/
|
||||
|
||||
Returns availability information on one quota, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/1/availability/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"available": true,
|
||||
"available_number": 419,
|
||||
"total_size": 1000,
|
||||
"pending_orders": 25,
|
||||
"paid_orders": 423,
|
||||
"cart_positions": 7,
|
||||
"blocking_vouchers": 126,
|
||||
"waiting_list": 0
|
||||
}
|
||||
|
||||
Note that ``total_size`` and ``available_number`` are ``null`` in case of unlimited quotas.
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the quota to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
217
doc/api/resources/subevents.rst
Normal file
@@ -0,0 +1,217 @@
|
||||
.. _rest-subevents:
|
||||
|
||||
Event series dates / Sub-events
|
||||
===============================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Events can represent whole event series if the ``has_subevents`` property of the event is active.
|
||||
In this case, many other resources are additionally connected to an event date (also called sub-event).
|
||||
The sub-event resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the sub-event
|
||||
name multi-lingual string The sub-event's full name
|
||||
event string The slug of the parent event
|
||||
active boolean If ``true``, the sub-event ticket shop is publicly
|
||||
available.
|
||||
date_from datetime The sub-event's start date
|
||||
date_to datetime The sub-event's end date (or ``null``)
|
||||
date_admission datetime The sub-event's admission date (or ``null``)
|
||||
presale_start datetime The sub-date at which the ticket shop opens (or ``null``)
|
||||
presale_end datetime The sub-date at which the ticket shop closes (or ``null``)
|
||||
location multi-lingual string The sub-event location (or ``null``)
|
||||
item_price_overrides list of objects List of items for which this sub-event overrides the
|
||||
default price
|
||||
├ item integer The internal item ID
|
||||
└ price money (string) The price or ``null`` for the default price
|
||||
variation_price_overrides list of objects List of variations for which this sub-event overrides
|
||||
the default price
|
||||
├ variation integer The internal variation ID
|
||||
└ price money (string) The price or ``null`` for the default price
|
||||
meta_data dict Values set for organizer-specific meta data parameters.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
The ``meta_data`` field has been added.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
|
||||
The ``event`` field has been added, together with filters on the list of dates and an organizer-level list.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/
|
||||
|
||||
Returns a list of all sub-events of an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/subevents/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "First Sample Conference"},
|
||||
"event": "sampleconf",
|
||||
"active": false,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 2,
|
||||
"price": "12.00"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/
|
||||
|
||||
Returns information on one sub-event, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/subevents/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "First Sample Conference"},
|
||||
"event": "sampleconf",
|
||||
"active": false,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 2,
|
||||
"price": "12.00"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {}
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``slug`` field of the sub-event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/subevents/
|
||||
|
||||
Returns a list of all sub-events of any event series you have access to within an organizer account.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/subevents/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "First Sample Conference"},
|
||||
"event": "sampleconf",
|
||||
"active": false,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 2,
|
||||
"price": "12.00"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": [],
|
||||
"meta_data": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query active: If set to ``true``/``false``, only events with a matching value of ``active`` are returned.
|
||||
:query event__live: If set to ``true``/``false``, only events with a matching value of ``live`` on the parent event are returned.
|
||||
:query is_future: If set to ``true`` (``false``), only events that happen currently or in the future are (not) returned.
|
||||
:query is_past: If set to ``true`` (``false``), only events that are over are (not) returned.
|
||||
:query ends_after: If set to a date and time, only events that happen during of after the given time are returned.
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
237
doc/api/resources/taxrules.rst
Normal file
@@ -0,0 +1,237 @@
|
||||
.. _rest-taxrules:
|
||||
|
||||
Tax rules
|
||||
=========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Tax rules specify how tax should be calculated for specific products. Custom taxation rule sets are currently to
|
||||
available via the API.
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the tax rule
|
||||
name multi-lingual string The tax rules' name
|
||||
rate decimal (string) Tax rate in percent
|
||||
price_includes_tax boolean If ``true`` (default), tax is assumed to be included in
|
||||
the specified product price
|
||||
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied
|
||||
home_country string Merchant country (required for reverse charge), can be
|
||||
``null`` or empty string
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
This resource has been added.
|
||||
|
||||
.. versionchanged:: 1.9
|
||||
|
||||
The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/taxrules/
|
||||
|
||||
Returns a list of all tax rules configured for an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/taxrules/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"home_country": "DE"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/taxrules/(id)/
|
||||
|
||||
Returns information on one tax rule, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/taxrules/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the tax rule to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/taxrules/
|
||||
|
||||
Create a new tax rule.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/taxrules/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 166
|
||||
|
||||
{
|
||||
"name": {"en": "VAT"},
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"rate": "19.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a tax rule for
|
||||
:param event: The ``slug`` field of the event to create a tax rule for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The tax rule could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create tax rules.
|
||||
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/taxrules/(id)/
|
||||
|
||||
Update a tax rule. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/taxrules/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 34
|
||||
|
||||
{
|
||||
"rate": "20.00",
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "VAT"},
|
||||
"rate": "20.00",
|
||||
"price_includes_tax": true,
|
||||
"eu_reverse_charge": false,
|
||||
"home_country": "DE"
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the tax rule to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The tax rule could not be modified due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it.
|
||||
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/taxrules/(id)/
|
||||
|
||||
Delete a tax rule. Note that tax rules can only be deleted if they are not in use for any products, settings
|
||||
or orders. If you cannot delete a tax rule, this method will return a ``403`` status code and you can only
|
||||
discontinue using it everywhere else.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/taxrules/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the tax rule to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event/rule does not exist **or** you have no permission to change it **or** this tax rule cannot be deleted since it is currently in use.
|
||||
316
doc/api/resources/vouchers.rst
Normal file
@@ -0,0 +1,316 @@
|
||||
Vouchers
|
||||
========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The voucher resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the voucher
|
||||
code string The voucher code that is required to redeem the voucher
|
||||
max_usages integer The maximum number of times this voucher can be
|
||||
redeemed (default: 1).
|
||||
redeemed integer The number of times this voucher already has been
|
||||
redeemed.
|
||||
valid_until datetime The voucher expiration date (or ``null``).
|
||||
block_quota boolean If ``True``, quota is blocked for this voucher.
|
||||
allow_ignore_quota boolean If ``True``, this voucher can be redeemed even if a
|
||||
product is sold out and even if quota is not blocked
|
||||
for this voucher.
|
||||
price_mode string Determines how this voucher affects product prices.
|
||||
Possible values:
|
||||
|
||||
* ``none`` – No effect on price
|
||||
* ``set`` – The product price is set to the given ``value``
|
||||
* ``subtract`` – The product price is determined by the original price *minus* the given ``value``
|
||||
* ``percent`` – The product price is determined by the original price reduced by the percentage given in ``value``
|
||||
value decimal (string) The value (see ``price_mode``)
|
||||
item integer An ID of an item this voucher is restricted to (or ``null``)
|
||||
variation integer An ID of a variation this voucher is restricted to (or ``null``)
|
||||
quota integer An ID of a quota this voucher is restricted to (or
|
||||
``null``). This is an exclusive alternative to
|
||||
``item`` and ``variation``: A voucher can be
|
||||
attached either to a specific product or to all
|
||||
products within one quota or it can be available
|
||||
for all items without restriction.
|
||||
tag string A string that is used for grouping vouchers
|
||||
comment string An internal comment on the voucher
|
||||
subevent integer ID of the date inside an event series this voucher belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.9
|
||||
|
||||
The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added.
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/vouchers/
|
||||
|
||||
Returns a list of all vouchers within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/vouchers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string code: Only show the voucher with the given voucher code.
|
||||
:query integer max_usages: Only show vouchers with the given maximal number of usages.
|
||||
:query integer redeemed: Only show vouchers with the given number of redemptions. Note that this doesn't tell you if
|
||||
the voucher can still be redeemed, as this also depends on ``max_usages``. See the
|
||||
``active`` query parameter as well.
|
||||
:query boolean block_quota: If set to ``true`` or ``false``, only vouchers with this value in the field
|
||||
``block_quota`` will be shown.
|
||||
:query boolean allow_ignore_quota: If set to ``true`` or ``false``, only vouchers with this value in the field
|
||||
``allow_ignore_quota`` will be shown.
|
||||
:query string price_mode: If set, only vouchers with this value in the field ``price_mode`` will be shown (see
|
||||
above).
|
||||
:query string value: If set, only vouchers with this value in the field ``value`` will be shown.
|
||||
:query integer item: If set, only vouchers attached to the item with the given ID will be shown.
|
||||
:query integer variation: If set, only vouchers attached to the variation with the given ID will be shown.
|
||||
:query integer quota: If set, only vouchers attached to the quota with the given ID will be shown.
|
||||
:query string tag: If set, only vouchers with the given tag will be shown.
|
||||
:query integer subevent: Only return vouchers of the sub-event with the given ID
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``code``,
|
||||
``max_usages``, ``valid_until``, and ``value``. Default: ``id``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/vouchers/(id)/
|
||||
|
||||
Returns information on one voucher, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/vouchers/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the voucher to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/vouchers/
|
||||
|
||||
Create a new voucher.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/vouchers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 408
|
||||
|
||||
{
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create a voucher for
|
||||
:param event: The ``slug`` field of the event to create a voucher for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The voucher could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this resource.
|
||||
:statuscode 409: The server was unable to acquire a lock and could not process your request. You can try again after a short waiting period.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/vouchers/(id)/
|
||||
|
||||
Update a voucher. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id`` and ``redeemed`` fields.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/vouchers/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 408
|
||||
|
||||
{
|
||||
"price_mode": "set",
|
||||
"value": "24.00"
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "24.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the voucher to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The voucher could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to change this resource.
|
||||
:statuscode 409: The server was unable to acquire a lock and could not process your request. You can try again after a short waiting period.
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/vouchers/(id)/
|
||||
|
||||
Delete a voucher. Note that you cannot delete a voucher if it already has been redeemed.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/vouchers/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the voucher to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this resource.
|
||||
287
doc/api/resources/waitinglist.rst
Normal file
@@ -0,0 +1,287 @@
|
||||
Waiting list entries
|
||||
====================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The waiting list entry resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the waiting list entry
|
||||
created datetime Creation date of the waiting list entry
|
||||
email string Email address of the user on the waiting list
|
||||
voucher integer Internal ID of the voucher sent to this user. If
|
||||
this field is set, the user has been sent a voucher
|
||||
and is no longer waiting. If it is ``null``, the
|
||||
user is still waiting.
|
||||
item integer An ID of an item the user is waiting to be available
|
||||
again
|
||||
variation integer An ID of a variation the user is waiting to be
|
||||
available again (or ``null``)
|
||||
locale string Locale of the waiting user
|
||||
subevent integer ID of the date inside an event series this entry belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.15
|
||||
|
||||
The write operations ``POST``, ``PATCH``, ``PUT``, and ``DELETE`` have been added as well as a method to send out
|
||||
vouchers.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/
|
||||
|
||||
Returns a list of all waiting list entries within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 2,
|
||||
"variation": null,
|
||||
"locale": "en",
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string email: Only show waiting list entries created with the given email address.
|
||||
:query string locale: Only show waiting list entries created with the given locale.
|
||||
:query boolean has_voucher: If set to ``true`` or ``false``, only waiting list entries are returned that have or
|
||||
have not been sent a voucher.
|
||||
:query integer item: If set, only entries of users waiting for the item with the given ID will be shown.
|
||||
:query integer variation: If set, only entries of users waiting for the variation with the given ID will be shown.
|
||||
:query integer subevent: Only return entries of the sub-event with the given ID
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``created``,
|
||||
``email``, ``item``. Default: ``created``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/(id)/
|
||||
|
||||
Returns information on one waiting list entry, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 2,
|
||||
"variation": null,
|
||||
"locale": "en",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the waiting list entry to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/
|
||||
|
||||
Create a new entry.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 408
|
||||
|
||||
{
|
||||
"email": "waiting@example.org",
|
||||
"item": 3,
|
||||
"variation": null,
|
||||
"locale": "de",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 3,
|
||||
"variation": null,
|
||||
"locale": "de",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to create an entry for
|
||||
:param event: The ``slug`` field of the event to create an entry for
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: The voucher could not be created due to invalid submitted data.
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this
|
||||
resource **or** entries cannot be created for this item at this time.
|
||||
|
||||
.. http:patch:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/(id)/
|
||||
|
||||
Update an entry. You can also use ``PUT`` instead of ``PATCH``. With ``PUT``, you have to provide all fields of
|
||||
the resource, other fields will be reset to default. With ``PATCH``, you only need to provide the fields that you
|
||||
want to change.
|
||||
|
||||
You can change all fields of the resource except the ``id``, ``voucher`` and ``created`` fields. You can only change
|
||||
an entry as long as no ``voucher`` is set.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
PATCH /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 408
|
||||
|
||||
{
|
||||
"item": 4
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 4,
|
||||
"variation": null,
|
||||
"locale": "de",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the entry to modify
|
||||
:statuscode 200: no error
|
||||
:statuscode 400: The entry could not be modified due to invalid submitted data
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to create this
|
||||
resource **or** entries cannot be created for this item at this time **or** this entry already
|
||||
has a voucher assigned
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/(id)/send_voucher/
|
||||
|
||||
Manually sends a voucher to someone on the waiting list
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/1/send_voucher/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
Content-Length: 0
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the entry to modify
|
||||
:statuscode 204: no error
|
||||
:statuscode 400: The voucher could not be sent out, see body for details (e.g. voucher has already been sent or
|
||||
item is not available).
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to do this
|
||||
|
||||
.. http:delete:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/(id)/
|
||||
|
||||
Delete an entry. Note that you cannot delete an entry once it is assigned a voucher.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
DELETE /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
Vary: Accept
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to modify
|
||||
:param event: The ``slug`` field of the event to modify
|
||||
:param id: The ``id`` field of the entry to delete
|
||||
:statuscode 204: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to delete this
|
||||
resource **or** this entry already has a voucher assigned.
|
||||
36
doc/api/tokenauth.rst
Normal file
@@ -0,0 +1,36 @@
|
||||
.. _`rest-tokenauth`:
|
||||
|
||||
Token-based authentication
|
||||
==========================
|
||||
|
||||
Obtaining an API token
|
||||
----------------------
|
||||
|
||||
To authenticate your API requests with Tokens, you need to obtain a team-level API token.
|
||||
You can create a token in the pretix web interface on the level of organizer teams. Create
|
||||
a new team or choose an existing team that has the level of permissions the token should
|
||||
have and create a new token using the form below the list of team members:
|
||||
|
||||
.. image:: img/token_form.png
|
||||
:class: screenshot
|
||||
|
||||
You can enter a description for the token to distinguish from other tokens later on.
|
||||
Once you click "Add", you will be provided with an API token in the success message.
|
||||
Copy this token, as you won't be able to retrieve it again.
|
||||
|
||||
.. image:: img/token_success.png
|
||||
:class: screenshot
|
||||
|
||||
Using an API token
|
||||
------------------
|
||||
|
||||
You need to include the API token with every request to pretix' API in the ``Authorization`` header
|
||||
like the following:
|
||||
|
||||
.. sourcecode:: http
|
||||
:emphasize-lines: 3
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Token e1l6gq2ye72thbwkacj7jbri7a7tvxe614ojv8ybureain92ocub46t5gab5966k
|
||||
|
||||
11
doc/checkin_filter.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from enchant.tokenize import get_tokenizer, Filter, unit_tokenize
|
||||
|
||||
class CheckinFilter(Filter):
|
||||
""" If a word looks like checkin_count, it refers to a so-called variable in
|
||||
the code, and is treated as being spelled right."""
|
||||
|
||||
def _split(self, word):
|
||||
if word[:8] == "checkin_":
|
||||
return unit_tokenize(word[8:])
|
||||
|
||||
return unit_tokenize(word)
|
||||
83
doc/conf.py
@@ -13,18 +13,31 @@
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
||||
from sphinx.util import compat
|
||||
compat.make_admonition = BaseAdmonition # See https://github.com/spinus/sphinxcontrib-images/issues/41
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
from datetime import date
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../src'))
|
||||
|
||||
import django
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix.settings")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix.testutils.settings")
|
||||
django.setup()
|
||||
|
||||
|
||||
try:
|
||||
import enchant
|
||||
HAS_PYENCHANT = True
|
||||
except:
|
||||
HAS_PYENCHANT = False
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
@@ -36,10 +49,12 @@ django.setup()
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinxcontrib.httpdomain',
|
||||
'sphinxcontrib.images',
|
||||
]
|
||||
if HAS_PYENCHANT:
|
||||
extensions.append('sphinxcontrib.spelling')
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@@ -51,20 +66,21 @@ source_suffix = '.rst'
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = 'contents'
|
||||
|
||||
# General information about the project.
|
||||
project = 'pretix'
|
||||
copyright = '2014-2016, Raphael Michel'
|
||||
copyright = '2014-{}, Raphael Michel'.format(date.today().year)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.0.0'
|
||||
from pretix import __version__
|
||||
version = '.'.join(__version__.split('.')[:2])
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.0.0'
|
||||
release = __version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -114,7 +130,9 @@ pygments_style = 'sphinx'
|
||||
# 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
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
html_theme_options = {
|
||||
'logo_only': True,
|
||||
}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
@@ -128,7 +146,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
html_logo = 'images/logo-white.svg'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
@@ -138,7 +156,11 @@ pygments_style = 'sphinx'
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = [
|
||||
'_static',
|
||||
os.path.abspath('../src/pretix/static/fonts/'),
|
||||
os.path.abspath('../src/pretix/static/fontawesome/fonts/'),
|
||||
]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
@@ -158,7 +180,9 @@ html_static_path = ['_static']
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
html_additional_pages = {
|
||||
'index': 'index.html'
|
||||
}
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_domain_indices = False
|
||||
@@ -170,7 +194,7 @@ html_use_index = False
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
@@ -189,11 +213,8 @@ html_use_index = False
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pretixdoc'
|
||||
|
||||
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()]
|
||||
html_theme = 'pretix_theme'
|
||||
html_theme_path = [os.path.abspath('_themes')]
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
@@ -213,7 +234,7 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'pretix.tex', 'pretix Documentation',
|
||||
('contents', 'pretix.tex', 'pretix Documentation',
|
||||
'Raphael Michel', 'manual'),
|
||||
]
|
||||
|
||||
@@ -273,3 +294,31 @@ texinfo_documents = [
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
images_config = {
|
||||
'default_image_width': '250px'
|
||||
}
|
||||
|
||||
linkcheck_ignore = [
|
||||
r'http://localhost.*', r'.*yourdomain.*', r'https://en.wikipedia.org', 'https://pretix.eu/',
|
||||
]
|
||||
|
||||
# -- Options for Spelling output ------------------------------------------
|
||||
if HAS_PYENCHANT:
|
||||
# String specifying the language, as understood by PyEnchant and enchant.
|
||||
# Defaults to en_US for US English.
|
||||
spelling_lang = 'en_US'
|
||||
|
||||
# String specifying a file containing a list of words known to be spelled
|
||||
# correctly but that do not appear in the language dictionary selected by
|
||||
# spelling_lang. The file should contain one word per line.
|
||||
spelling_word_list_filename='spelling_wordlist.txt'
|
||||
|
||||
# Boolean controlling whether suggestions for misspelled words are printed.
|
||||
# Defaults to False.
|
||||
spelling_show_suggestions=True
|
||||
|
||||
# List of filter classes to be added to the tokenizer that produces words to be checked.
|
||||
from checkin_filter import CheckinFilter
|
||||
spelling_filters=[CheckinFilter]
|
||||
|
||||
12
doc/contents.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
user/index
|
||||
admin/index
|
||||
api/index
|
||||
development/index
|
||||
plugins/index
|
||||
|
||||
@@ -25,7 +25,7 @@ If you want to add a custom view to the control area of an event, just register
|
||||
views.admin_view, name='backend'),
|
||||
]
|
||||
|
||||
It is required that your URL paramaters are called ``organizer`` and ``event``. If you want to
|
||||
It is required that your URL parameters are called ``organizer`` and ``event``. If you want to
|
||||
install a view on organizer level, you can leave out the ``event``.
|
||||
|
||||
You can then implement the view as you would normally do. Our middleware will automatically
|
||||
@@ -60,7 +60,85 @@ your views::
|
||||
def admin_view(request, organizer, event):
|
||||
...
|
||||
|
||||
Similarly, there is ``organizer_permission_required`` and ``OrganizerPermissionRequiredMixin``.
|
||||
Similarly, there is ``organizer_permission_required`` and ``OrganizerPermissionRequiredMixin``. In case of
|
||||
event-related views, there is also a signal that allows you to add the view to the event navigation like this::
|
||||
|
||||
|
||||
from django.urls import resolve, reverse
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from pretix.control.signals import nav_event
|
||||
|
||||
|
||||
@receiver(nav_event, dispatch_uid='friends_tickets_nav')
|
||||
def navbar_info(sender, request, **kwargs):
|
||||
url = resolve(request.path_info)
|
||||
if not request.user.has_event_permission(request.organizer, request.event, 'can_change_vouchers'):
|
||||
return []
|
||||
return [{
|
||||
'label': _('My plugin view'),
|
||||
'icon': 'heart',
|
||||
'url': reverse('plugins:myplugin:index', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.organizer.slug,
|
||||
}),
|
||||
'active': url.namespace == 'plugins:myplugin' and url.url_name == 'review',
|
||||
}]
|
||||
|
||||
|
||||
Event settings view
|
||||
-------------------
|
||||
|
||||
A special case of a control panel view is a view hooked into the event settings page. For this case, there is a
|
||||
special navigation signal::
|
||||
|
||||
@receiver(nav_event_settings, dispatch_uid='friends_tickets_nav_settings')
|
||||
def navbar_settings(sender, request, **kwargs):
|
||||
url = resolve(request.path_info)
|
||||
return [{
|
||||
'label': _('My settings'),
|
||||
'url': reverse('plugins:myplugin:settings', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.organizer.slug,
|
||||
}),
|
||||
'active': url.namespace == 'plugins:myplugin' and url.url_name == 'settings',
|
||||
}]
|
||||
|
||||
Also, your view should inherit from ``EventSettingsViewMixin`` and your template from ``pretixcontrol/event/settings_base.html``
|
||||
for good integration. If you just want to display a form, you could do it like the following::
|
||||
|
||||
class MySettingsView(EventSettingsViewMixin, EventSettingsFormView):
|
||||
model = Event
|
||||
permission = 'can_change_settings'
|
||||
form_class = MySettingsForm
|
||||
template_name = 'my_plugin/settings.html'
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse('plugins:myplugin:settings', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
With this template::
|
||||
|
||||
{% extends "pretixcontrol/event/settings_base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %} {% trans "Friends Tickets Settings" %} {% endblock %}
|
||||
{% block inside %}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Friends Tickets Settings" %}</legend>
|
||||
{% bootstrap_form form layout="horizontal" %}
|
||||
</fieldset>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
Frontend views
|
||||
--------------
|
||||
@@ -68,31 +146,79 @@ Frontend views
|
||||
Including a custom view into the participant-facing frontend is a little bit different as there is
|
||||
no path prefix like ``control/``.
|
||||
|
||||
First, define your URL in your ``urls.py``, but this time in the ``event_patterns`` section::
|
||||
First, define your URL in your ``urls.py``, but this time in the ``event_patterns`` section and wrapped by
|
||||
``event_url``::
|
||||
|
||||
from django.conf.urls import url
|
||||
from pretix.multidomain import event_url
|
||||
|
||||
from . import views
|
||||
|
||||
event_patterns = [
|
||||
url(r'^mypluginname/', views.frontend_view, name='frontend'),
|
||||
event_url(r'^mypluginname/', views.frontend_view, name='frontend'),
|
||||
]
|
||||
|
||||
You can then implement a view as you would normally do, but you need to apply a decorator to your
|
||||
view if you want pretix's default behavior::
|
||||
|
||||
from pretix.presale.utils import event_view
|
||||
|
||||
@event_view
|
||||
def some_event_view(request, *args, **kwargs):
|
||||
...
|
||||
|
||||
This decorator will check the URL arguments for their ``event`` and ``organizer`` parameters and
|
||||
correctly ensure that:
|
||||
You can then implement a view as you would normally do. It will be automatically ensured that:
|
||||
|
||||
* The requested event exists
|
||||
* The requested event is activated (can be overridden by decorating with ``@event_view(require_live=False)``)
|
||||
* The requested event is active (you can disable this check using ``event_url(…, require_live=True)``)
|
||||
* The event is accessed via the domain it should be accessed
|
||||
* The ``request.event`` attribute contains the correct ``Event`` object
|
||||
* The ``request.organizer`` attribute contains the correct ``Organizer`` object
|
||||
* Your plugin is enabled
|
||||
* The locale is set correctly
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
The ``event_url()`` wrapper has been added in 1.7 to replace the former ``@event_view`` decorator. The
|
||||
``event_url()`` wrapper is optional and using ``url()`` still works, but you will not be able to set the
|
||||
``require_live`` setting any more via the decorator. The ``@event_view`` decorator is now deprecated and
|
||||
does nothing.
|
||||
|
||||
REST API viewsets
|
||||
-----------------
|
||||
|
||||
Our REST API is built upon `Django REST Framework`_ (DRF). DRF has two important concepts that are different from
|
||||
standard Django request handling: There are `ViewSets`_ to group related views in a single class and `Routers`_ to
|
||||
automatically build URL configurations from them.
|
||||
|
||||
To integrate a custom viewset with pretix' REST API, you can just register with one of our routers within the
|
||||
``urls.py`` module of your plugin::
|
||||
|
||||
|
||||
from pretix.api.urls import event_router, router, orga_router
|
||||
|
||||
router.register('global_viewset', MyViewSet)
|
||||
orga_router.register('orga_level_viewset', MyViewSet)
|
||||
event_router.register('event_level_viewset', MyViewSet)
|
||||
|
||||
Routes registered with ``router`` are inserted into the global API space at ``/api/v1/``. Routes registered with
|
||||
``orga_router`` will be included at ``/api/v1/organizers/(organizer)/`` and routes registered with ``event_router``
|
||||
will be included at ``/api/v1/organizers/(organizer)/events/(event)/``.
|
||||
|
||||
In case of ``orga_router`` and ``event_router``, permission checking is done for you similarly as with custom views
|
||||
in the control panel. However, you need to make sure on your own only to return the correct subset of data! ``request
|
||||
.event`` and ``request.organizer`` are available as usual.
|
||||
|
||||
To require a special permission like ``can_view_orders``, you do not need to inherit from a special ViewSet base
|
||||
class, you can just set the ``permission`` attribute on your viewset::
|
||||
|
||||
class MyViewSet(ModelViewSet):
|
||||
permission = 'can_view_orders'
|
||||
...
|
||||
|
||||
If you want to check the permission only for some methods of your viewset, you have to do it yourself. Note here that
|
||||
API authentications can be done via user sessions or API tokens and you should therefore check something like the
|
||||
following::
|
||||
|
||||
|
||||
perm_holder = (request.auth if isinstance(request.auth, TeamAPIToken) else request.user)
|
||||
if perm_holder.has_event_permission(request.event.organizer, request.event, 'can_view_orders'):
|
||||
...
|
||||
|
||||
|
||||
.. warning:: It is important that you do this in the ``yourplugin.urls`` module, otherwise pretix will not find your
|
||||
routes early enough during system startup.
|
||||
|
||||
.. _Django REST Framework: http://www.django-rest-framework.org/
|
||||
.. _ViewSets: http://www.django-rest-framework.org/api-guide/viewsets/
|
||||
.. _Routers: http://www.django-rest-framework.org/api-guide/routers/
|
||||
|
||||
109
doc/development/api/email.rst
Normal file
@@ -0,0 +1,109 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Writing an HTML e-mail renderer plugin
|
||||
======================================
|
||||
|
||||
An email renderer class controls how the HTML part of e-mails sent by pretix is built.
|
||||
The creation of such a plugin is very similar to creating an export output.
|
||||
|
||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
||||
|
||||
Output registration
|
||||
-------------------
|
||||
|
||||
The email HTML renderer API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available email renderers. Your plugin
|
||||
should listen for this signal and return the subclass of ``pretix.base.email.BaseHTMLMailRenderer``
|
||||
that we'll provide in this plugin::
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_html_mail_renderers
|
||||
|
||||
|
||||
@receiver(register_html_mail_renderers, dispatch_uid="renderer_custom")
|
||||
def register_mail_renderers(sender, **kwargs):
|
||||
from .email import MyMailRenderer
|
||||
return MyMailRenderer
|
||||
|
||||
|
||||
The renderer class
|
||||
------------------
|
||||
|
||||
.. class:: pretix.base.email.BaseHTMLMailRenderer
|
||||
|
||||
The central object of each email renderer is the subclass of ``BaseHTMLMailRenderer``.
|
||||
|
||||
.. py:attribute:: BaseHTMLMailRenderer.event
|
||||
|
||||
The default constructor sets this property to the event we are currently
|
||||
working for.
|
||||
|
||||
.. autoattribute:: identifier
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: verbose_name
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: thumbnail_filename
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: is_available
|
||||
|
||||
.. automethod:: render
|
||||
|
||||
This is an abstract method, you **must** implement this!
|
||||
|
||||
Helper class for template-base renderers
|
||||
----------------------------------------
|
||||
|
||||
The email renderer that ships with pretix is based on Django templates to generate HTML.
|
||||
In case you also want to render emails based on a template, we provided a ready-made base
|
||||
class ``TemplateBasedMailRenderer`` that you can re-use to perform the following steps:
|
||||
|
||||
* Convert the body text and the signature to HTML using our markdown renderer
|
||||
|
||||
* Render the template
|
||||
|
||||
* Call `inlinestyler`_ to convert all ``<style>`` style sheets to inline ``style=""``
|
||||
attributes for better compatibility
|
||||
|
||||
To use it, you just need to implement some variables::
|
||||
|
||||
class ClassicMailRenderer(TemplateBasedMailRenderer):
|
||||
verbose_name = _('pretix default')
|
||||
identifier = 'classic'
|
||||
thumbnail_filename = 'pretixbase/email/thumb.png'
|
||||
template_name = 'pretixbase/email/plainwrapper.html'
|
||||
|
||||
The template is passed the following context variables:
|
||||
|
||||
``site``
|
||||
Name of the pretix installation (``settings.PRETIX_INSTANCE_NAME``)
|
||||
|
||||
``site_url``
|
||||
Root URL of the pretix installation (``settings.SITE_URL``)
|
||||
|
||||
``body``
|
||||
The body as markdown (render with ``{{ body|safe }}``)
|
||||
|
||||
``subject``
|
||||
The email subject
|
||||
|
||||
``color``
|
||||
The primary color of the event
|
||||
|
||||
``event``
|
||||
The ``Event`` object
|
||||
|
||||
``signature`` (optional, only if configured)
|
||||
The body as markdown (render with ``{{ signature|safe }}``)
|
||||
|
||||
``order`` (optional, only if applicable)
|
||||
The ``Order`` object
|
||||
|
||||
.. _inlinestyler: https://pypi.org/project/inlinestyler/
|
||||
@@ -21,10 +21,10 @@ that we'll provide in this plugin::
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_data_exporter
|
||||
from pretix.base.signals import register_data_exporters
|
||||
|
||||
|
||||
@receiver(register_data_exporter, dispatch_uid="exporter_myexporter")
|
||||
@receiver(register_data_exporters, dispatch_uid="exporter_myexporter")
|
||||
def register_data_exporter(sender, **kwargs):
|
||||
from .exporter import MyExporter
|
||||
return MyExporter
|
||||
|
||||
@@ -11,7 +11,8 @@ Core
|
||||
----
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: periodic_task, event_live_issues
|
||||
:members: periodic_task, event_live_issues, event_copy_data, email_filter, register_notification_types,
|
||||
item_copy_data
|
||||
|
||||
Order events
|
||||
""""""""""""
|
||||
@@ -19,13 +20,13 @@ Order events
|
||||
There are multiple signals that will be sent out in the ordering cycle:
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: validate_cart, order_paid, order_placed
|
||||
:members: validate_cart, order_fee_calculation, order_paid, order_placed, order_fee_type_name, allow_ticket_download
|
||||
|
||||
Frontend
|
||||
--------
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, checkout_confirm_messages
|
||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, fee_calculation_for_cart, contact_form_fields, question_form_fields, checkout_confirm_messages, checkout_confirm_page_content
|
||||
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
@@ -47,20 +48,33 @@ Backend
|
||||
-------
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:members: nav_event, html_head, quota_detail_html, nav_topbar, organizer_edit_tabs
|
||||
:members: nav_event, html_head, html_page_start, quota_detail_html, nav_topbar, nav_global, nav_organizer, nav_event_settings,
|
||||
order_info, event_settings_widget, oauth_application_registered
|
||||
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: logentry_display, requiredaction_display
|
||||
:members: logentry_display, logentry_object_link, requiredaction_display
|
||||
|
||||
Vouchers
|
||||
""""""""
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:members: voucher_form_class, voucher_form_html
|
||||
:members: item_forms
|
||||
|
||||
Vouchers
|
||||
""""""""
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:members: voucher_form_class, voucher_form_html, voucher_form_validation
|
||||
|
||||
Dashboards
|
||||
""""""""""
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:members: event_dashboard_widgets, user_dashboard_widgets
|
||||
|
||||
Ticket designs
|
||||
""""""""""""""
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: layout_text_variables
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Plugin hooks
|
||||
============
|
||||
Plugin development
|
||||
==================
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -10,5 +10,10 @@ Contents:
|
||||
exporter
|
||||
ticketoutput
|
||||
payment
|
||||
payment_2.0
|
||||
email
|
||||
invoice
|
||||
shredder
|
||||
customview
|
||||
general
|
||||
quality
|
||||
|
||||
95
doc/development/api/invoice.rst
Normal file
@@ -0,0 +1,95 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Writing an invoice renderer plugin
|
||||
==================================
|
||||
|
||||
An invoice renderer controls how invoice files are built.
|
||||
The creation of such a plugin is very similar to creating an export output.
|
||||
|
||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
||||
|
||||
Output registration
|
||||
-------------------
|
||||
|
||||
The invoice renderer API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available invoice renderers. Your plugin
|
||||
should listen for this signal and return the subclass of ``pretix.base.invoice.BaseInvoiceRenderer``
|
||||
that we'll provide in this plugin::
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_invoice_renderers
|
||||
|
||||
|
||||
@receiver(register_invoice_renderers, dispatch_uid="output_custom")
|
||||
def register_infoice_renderers(sender, **kwargs):
|
||||
from .invoice import MyInvoiceRenderer
|
||||
return MyInvoiceRenderer
|
||||
|
||||
|
||||
The renderer class
|
||||
------------------
|
||||
|
||||
.. class:: pretix.base.invoice.BaseInvoiceRenderer
|
||||
|
||||
The central object of each invoice renderer is the subclass of ``BaseInvoiceRenderer``.
|
||||
|
||||
.. py:attribute:: BaseInvoiceRenderer.event
|
||||
|
||||
The default constructor sets this property to the event we are currently
|
||||
working for.
|
||||
|
||||
.. autoattribute:: identifier
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: verbose_name
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. automethod:: generate
|
||||
|
||||
Helper class for reportlab-base renderers
|
||||
-----------------------------------------
|
||||
|
||||
All PDF rendering that ships with pretix is based on reportlab. We recommend to read the
|
||||
`reportlab User Guide`_ to understand all the concepts used here.
|
||||
|
||||
If you want to implement a renderer that also uses report lab, this helper class might be
|
||||
convenient to you:
|
||||
|
||||
|
||||
.. class:: pretix.base.invoice.BaseReportlabInvoiceRenderer
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.pagesize
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.left_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.right_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.top_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.bottom_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.doc_template_class
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.invoice
|
||||
|
||||
.. automethod:: _init
|
||||
|
||||
.. automethod:: _get_stylesheet
|
||||
|
||||
.. automethod:: _register_fonts
|
||||
|
||||
.. automethod:: _on_first_page
|
||||
|
||||
.. automethod:: _on_other_page
|
||||
|
||||
.. automethod:: _get_first_page_frames
|
||||
|
||||
.. automethod:: _get_other_page_frames
|
||||
|
||||
.. automethod:: _build_doc
|
||||
|
||||
.. _reportlab User Guide: https://www.reportlab.com/docs/reportlab-userguide.pdf
|
||||
@@ -9,6 +9,10 @@ is very similar to creating an export output.
|
||||
|
||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
||||
|
||||
.. warning:: We changed our payment provider API a lot in pretix 2.x. Our documentation page on :ref:`payment2.0`
|
||||
might be insightful even if you do not have a payment provider to port, as it outlines the rationale
|
||||
behind the current design.
|
||||
|
||||
Provider registration
|
||||
---------------------
|
||||
|
||||
@@ -31,7 +35,7 @@ that the plugin will provide::
|
||||
The provider class
|
||||
------------------
|
||||
|
||||
.. class:: pretix.base.payment.BasePaymentProvider
|
||||
.. py:class:: pretix.base.payment.BasePaymentProvider
|
||||
|
||||
The central object of each payment provider is the subclass of ``BasePaymentProvider``.
|
||||
|
||||
@@ -54,53 +58,59 @@ The provider class
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: is_enabled
|
||||
.. autoattribute:: public_name
|
||||
|
||||
.. automethod:: calculate_fee
|
||||
.. autoattribute:: is_enabled
|
||||
|
||||
.. autoattribute:: settings_form_fields
|
||||
|
||||
.. automethod:: settings_content_render
|
||||
|
||||
.. automethod:: render_invoice_text
|
||||
.. automethod:: is_allowed
|
||||
|
||||
.. automethod:: payment_form_render
|
||||
|
||||
.. automethod:: payment_form
|
||||
|
||||
.. automethod:: is_allowed
|
||||
|
||||
.. autoattribute:: payment_form_fields
|
||||
|
||||
.. automethod:: checkout_prepare
|
||||
|
||||
.. automethod:: payment_is_valid_session
|
||||
|
||||
.. automethod:: checkout_prepare
|
||||
|
||||
.. automethod:: checkout_confirm_render
|
||||
|
||||
This is an abstract method, you **must** override this!
|
||||
|
||||
.. automethod:: payment_perform
|
||||
.. automethod:: execute_payment
|
||||
|
||||
.. automethod:: calculate_fee
|
||||
|
||||
.. automethod:: order_pending_mail_render
|
||||
|
||||
.. automethod:: order_pending_render
|
||||
.. automethod:: payment_pending_render
|
||||
|
||||
This is an abstract method, you **must** override this!
|
||||
.. autoattribute:: abort_pending_allowed
|
||||
|
||||
.. automethod:: render_invoice_text
|
||||
|
||||
.. automethod:: order_change_allowed
|
||||
|
||||
.. automethod:: order_can_retry
|
||||
.. automethod:: payment_prepare
|
||||
|
||||
.. automethod:: order_prepare
|
||||
.. automethod:: payment_control_render
|
||||
|
||||
.. automethod:: order_paid_render
|
||||
.. automethod:: payment_refund_supported
|
||||
|
||||
.. automethod:: order_control_render
|
||||
.. automethod:: payment_partial_refund_supported
|
||||
|
||||
.. automethod:: order_control_refund_render
|
||||
.. automethod:: execute_refund
|
||||
|
||||
.. automethod:: order_control_refund_perform
|
||||
.. automethod:: shred_payment_info
|
||||
|
||||
.. autoattribute:: is_implicit
|
||||
|
||||
.. autoattribute:: is_meta
|
||||
|
||||
|
||||
Additional views
|
||||
|
||||
129
doc/development/api/payment_2.0.rst
Normal file
@@ -0,0 +1,129 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
.. _`payment2.0`:
|
||||
|
||||
Porting a payment provider from pretix 1.x to pretix 2.x
|
||||
========================================================
|
||||
|
||||
In pretix 2.x, we changed large parts of the payment provider API. This documentation details the changes we made
|
||||
and shows you how you can make an existing pretix 1.x payment provider compatible with pretix 2.x
|
||||
|
||||
Conceptual overview
|
||||
-------------------
|
||||
|
||||
In pretix 1.x, an order was always directly connected to a payment provider for the full life of an order. As long as
|
||||
an order was unpaid, this could still be changed in some cases, but once an order was paid, no changes to the payment
|
||||
provider were possible any more. Additionally, the internal state of orders allowed orders only to be fully paid or
|
||||
not paid at all. This leads to a couple of consequences:
|
||||
|
||||
* Payment-related functions (like "execute payment" or "do a refund") always operated on full orders.
|
||||
|
||||
* Changing the total of an order was basically impossible once an order was paid, since there was no concept of
|
||||
partial payments or partial refunds.
|
||||
|
||||
* Payment provider plugins needed to take complicated steps to detect cases that require human intervention, like e.g.
|
||||
|
||||
* An order has expired, no quota is left to revive it, but a payment has been received
|
||||
|
||||
* A payment has been received for a canceled order
|
||||
|
||||
* A payment has been received for an order that has already been paid with a different payment method
|
||||
|
||||
* An external payment service notified us of a refund/dispute
|
||||
|
||||
We noticed that we copied and repeated large portions of code in all our official payment provider plugins, just
|
||||
to deal with some of these cases.
|
||||
|
||||
* Sometimes, there is the need to mark an order as refunded within pretix, without automatically triggering a refund
|
||||
with an external API. Every payment method needed to implement a user interface for this independently.
|
||||
|
||||
* If a refund was not possible automatically, there was no way user to track which payments actually have been refunded
|
||||
manually and which are still left to do.
|
||||
|
||||
* When the payment with one payment provider failed and the user changed to a different payment provider, all
|
||||
information about the first payment was lost from the order object and could only be retrieved from order log data,
|
||||
which also made it hard to design a data shredder API to get rid of this data.
|
||||
|
||||
In pretix 2.x, we introduced two new models, :py:class:`OrderPayment <pretix.base.models.OrderPayment>` and
|
||||
:py:class:`OrderRefund <pretix.base.models.OrderRefund>`. Each instance of these is connected to an order and
|
||||
represents one single attempt to pay or refund a specific amount of money. Each one of these has an individual state,
|
||||
can individually fail or succeed, and carries an amount variable that can differ from the order total.
|
||||
|
||||
This has the following advantages:
|
||||
|
||||
* The system can now detect orders that are over- or underpaid, independent of the payment providers in use.
|
||||
|
||||
* Therefore, we can now allow partial payments, partial refunds, and changing paid orders, and automatically detect
|
||||
the cases listed above and notify the user.
|
||||
|
||||
Payment providers now interact with those payment and refund objects more than with orders.
|
||||
|
||||
Your to-do list
|
||||
---------------
|
||||
|
||||
Payment processing
|
||||
""""""""""""""""""
|
||||
|
||||
* The method ``BasePaymentProvider.order_pending_render`` has been removed and replaced by a new
|
||||
``BasePaymentProvider.payment_pending_render(request, payment)`` method that is passed an ``OrderPayment``
|
||||
object instead of an ``Order``.
|
||||
|
||||
* The method ``BasePaymentProvider.payment_form_render`` now receives a new ``total`` parameter.
|
||||
|
||||
* The method ``BasePaymentProvider.payment_perform`` has been removed and replaced by a new method
|
||||
``BasePaymentProvider.execute_payment(request, payment)`` that is passed an ``OrderPayment``
|
||||
object instead of an ``Order``.
|
||||
|
||||
* The function ``pretix.base.services.mark_order_paid`` has been removed, instead call ``payment.confirm()``
|
||||
on a pending ``OrderPayment`` object. If no further payments are required for this order, this will also
|
||||
mark the order as paid automatically. Note that ``payment.confirm()`` can still throw a ``QuotaExceededException``,
|
||||
however it will still mark the payment as complete (not the order!), so you should catch this exception and
|
||||
inform the user, but not abort the transaction.
|
||||
|
||||
* A new property ``BasePaymentProvider.abort_pending_allowed`` has been introduced. Only if set, the user will
|
||||
be able to retry a payment or switch the payment method when the order currently has a payment object in
|
||||
state ``"pending"``. This replaces ``BasePaymentProvider.order_can_retry``, which no longer exists.
|
||||
|
||||
* The methods ``BasePaymentProvider.retry_prepare`` and ``BasePaymentProvider.order_prepare`` have both been
|
||||
replaced by a new method ``BasePaymentProvider.payment_prepare(request, payment)`` that is passed an ``OrderPayment``
|
||||
object instead of an ``Order``. **Keep in mind that this payment object might have an amount property that
|
||||
differs from the order total, if the order is already partially paid.**
|
||||
|
||||
* The method ``BasePaymentProvider.order_paid_render`` has been removed.
|
||||
|
||||
* The method ``BasePaymentProvider.order_control_render`` has been removed and replaced by a new method
|
||||
``BasePaymentProvider.payment_control_render(request, payment)`` that is passed an ``OrderPayment``
|
||||
object instead of an ``Order``.
|
||||
|
||||
* There's no need to manually deal with excess payments or duplicate payments anymore, just setting the ``OrderPayment``
|
||||
methods to the correct state will do the job.
|
||||
|
||||
Creating refunds
|
||||
""""""""""""""""
|
||||
|
||||
* The methods ``BasePaymentProvider.order_control_refund_render`` and ``BasePaymentProvider.order_control_refund_perform``
|
||||
have been removed.
|
||||
|
||||
* Two new boolean methods ``BasePaymentProvider.payment_refund_supported(payment)`` and ``BasePaymentProvider.payment_partial_refund_supported(payment)``
|
||||
have been introduced. They should be set to return ``True`` if and only if the payment API allows to *automatically*
|
||||
transfer the money back to the customer.
|
||||
|
||||
* A new method ``BasePaymentProvider.execute_refund(refund)`` has been introduced. This method is called using a
|
||||
``OrderRefund`` object in ``"created"`` state and is expected to transfer the money back and confirm success with
|
||||
calling ``refund.done()``. This will only ever be called if either ``BasePaymentProvider.payment_refund_supported(payment)``
|
||||
or ``BasePaymentProvider.payment_partial_refund_supported(payment)`` return ``True``.
|
||||
|
||||
Processing external refunds
|
||||
"""""""""""""""""""""""""""
|
||||
|
||||
* If e.g. a webhook API notifies you that a payment has been disputed or refunded with the external API, you are
|
||||
expected to call ``OrderPayment.create_external_refund(self, amount, execution_date, info='{}')`` on this payment.
|
||||
This will create and return an appropriate ``OrderRefund`` object and send out a notification. However, it will not
|
||||
mark the order as refunded, but will ask the event organizer for a decision.
|
||||
|
||||
Data shredders
|
||||
""""""""""""""
|
||||
|
||||
* The method ``BasePaymentProvider.shred_payment_info`` is no longer passed an order, but instead **either**
|
||||
an ``OrderPayment`` **or** an ``OrderRefund``.
|
||||
@@ -1,8 +1,10 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Plugin basics
|
||||
=============
|
||||
.. _`pluginsetup`:
|
||||
|
||||
Creating a plugin
|
||||
=================
|
||||
|
||||
It is possible to extend pretix with custom Python code using the official plugin
|
||||
API. Every plugin has to be implemented as an independent Django 'app' living
|
||||
@@ -14,10 +16,15 @@ The communication between pretix and the plugins happens mostly using Django's
|
||||
``pretix.control`` and ``pretix.presale`` expose a number of signals which are documented
|
||||
on the next pages.
|
||||
|
||||
.. _`pluginsetup`:
|
||||
|
||||
To create a new plugin, create a new python package which must be a valid `Django app`_
|
||||
and must contain plugin metadata, as described below.
|
||||
There is some boilerplate that you will need for every plugin to get started. To save your
|
||||
time, we created a `cookiecutter`_ template that you can use like this::
|
||||
|
||||
$ pip install cookiecutter
|
||||
$ cookiecutter https://github.com/pretix/pretix-plugin-cookiecutter
|
||||
|
||||
This will ask you some questions and then create a project folder for your plugin.
|
||||
|
||||
The following pages go into detail about the several types of plugins currently
|
||||
supported. While these instructions don't assume that you know a lot about pretix,
|
||||
@@ -30,35 +37,29 @@ Plugin metadata
|
||||
The plugin metadata lives inside a ``PretixPluginMeta`` class inside your app's
|
||||
configuration class. The metadata class must define the following attributes:
|
||||
|
||||
``name`` (``str``):
|
||||
The human-readable name of your plugin
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
``author`` (``str``):
|
||||
Your name
|
||||
|
||||
``version`` (``str``):
|
||||
A human-readable version code of your plugin
|
||||
|
||||
``description`` (``str``):
|
||||
A more verbose description of what your plugin does.
|
||||
|
||||
``visible`` (``bool``):
|
||||
``True`` by default, can hide a plugin so it cannot be normally activated.
|
||||
|
||||
``restricted`` (``bool``):
|
||||
``False`` by default, restricts a plugin such that it can only be enabled for an event
|
||||
by system administrators / superusers.
|
||||
================== ==================== ===========================================================
|
||||
Attribute Type Description
|
||||
================== ==================== ===========================================================
|
||||
name string The human-readable name of your plugin
|
||||
author string Your name
|
||||
version string A human-readable version code of your plugin
|
||||
description string A more verbose description of what your plugin does.
|
||||
visible boolean (optional) ``True`` by default, can hide a plugin so it cannot be normally activated.
|
||||
restricted boolean (optional) ``False`` by default, restricts a plugin such that it can only be enabled
|
||||
for an event by system administrators / superusers.
|
||||
================== ==================== ===========================================================
|
||||
|
||||
A working example would be::
|
||||
|
||||
# file: pretix/plugins/timerestriction/__init__.py
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class PaypalApp(AppConfig):
|
||||
name = 'pretix.plugins.paypal'
|
||||
verbose_name = _("Stripe")
|
||||
name = 'pretix_paypal'
|
||||
verbose_name = _("PayPal")
|
||||
|
||||
class PretixPluginMeta:
|
||||
name = _("PayPal")
|
||||
@@ -69,8 +70,7 @@ A working example would be::
|
||||
description = _("This plugin allows you to receive payments via PayPal")
|
||||
|
||||
|
||||
default_app_config = 'pretix.plugins.paypal.PaypalApp'
|
||||
|
||||
default_app_config = 'pretix_paypal.PaypalApp'
|
||||
|
||||
The ``AppConfig`` class may implement a property ``compatiblity_errors``, that checks
|
||||
whether the pretix installation meets all requirements of the plugin. If so,
|
||||
@@ -87,11 +87,10 @@ make use of the `entry point`_ feature of setuptools. To register a plugin that
|
||||
in a separate python package, your ``setup.py`` should contain something like this::
|
||||
|
||||
setup(
|
||||
…
|
||||
|
||||
args...,
|
||||
entry_points="""
|
||||
[pretix.plugin]
|
||||
sampleplugin=sampleplugin:PretixPluginMeta
|
||||
pretix_paypal=pretix_paypal:PretixPluginMeta
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -109,12 +108,25 @@ pages. We suggest that you put your signal receivers into a ``signals`` submodul
|
||||
of your plugin. You should extend your ``AppConfig`` (see above) by the following
|
||||
method to make your receivers available::
|
||||
|
||||
class TimeRestrictionApp(AppConfig):
|
||||
class PaypalApp(AppConfig):
|
||||
…
|
||||
|
||||
def ready(self):
|
||||
from . import signals # NOQA
|
||||
|
||||
You can optionally specify code that is executed when your plugin is activated for an event
|
||||
in the ``installed`` method::
|
||||
|
||||
class PaypalApp(AppConfig):
|
||||
…
|
||||
|
||||
def installed(self, event):
|
||||
pass # Your code here
|
||||
|
||||
|
||||
Note that ``installed`` will *not* be called if the plugin in indirectly activated for an event
|
||||
because the event is created with settings copied from another event.
|
||||
|
||||
Views
|
||||
-----
|
||||
|
||||
@@ -130,4 +142,5 @@ your Django app label.
|
||||
.. _Django app: https://docs.djangoproject.com/en/1.7/ref/applications/
|
||||
.. _signal dispatcher: https://docs.djangoproject.com/en/1.7/topics/signals/
|
||||
.. _namespace packages: http://legacy.python.org/dev/peps/pep-0420/
|
||||
.. _entry point: https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins
|
||||
.. _entry point: https://setuptools.readthedocs.io/en/latest/pkg_resources.html#locating-plugins
|
||||
.. _cookiecutter: https://cookiecutter.readthedocs.io/en/latest/
|
||||
|
||||
125
doc/development/api/quality.rst
Normal file
@@ -0,0 +1,125 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
.. _`pluginquality`:
|
||||
|
||||
Plugin quality checklist
|
||||
========================
|
||||
|
||||
If you want to write a high-quality pretix plugin, this is a list of things you should check before
|
||||
you publish it. This is also a list of things that we check, if we consider installing an externally
|
||||
developed plugin on our hosted infrastructure.
|
||||
|
||||
A. Meta
|
||||
-------
|
||||
|
||||
#. The plugin is clearly licensed under an appropriate license.
|
||||
|
||||
#. The plugin has an unambiguous name, description, and author metadata.
|
||||
|
||||
#. The plugin has a clear versioning scheme and the latest version of the plugin is kept compatible to the latest
|
||||
stable version of pretix.
|
||||
|
||||
#. The plugin is properly packaged using standard Python packaging tools.
|
||||
|
||||
#. The plugin correctly declares its external dependencies.
|
||||
|
||||
#. A contact address is provided in case of security issues.
|
||||
|
||||
B. Isolation
|
||||
------------
|
||||
|
||||
#. If any signal receivers use the `dispatch_uid`_ feature, the UIDs are prefixed by the plugin's name and do not
|
||||
clash with other plugins.
|
||||
|
||||
#. If any templates or static files are shipped, they are located in subdirectories with the name of the plugin and do
|
||||
not clash with other plugins or core files.
|
||||
|
||||
#. Any keys stored to the settings store are prefixed with the plugin's name and do not clash with other plugins or
|
||||
core.
|
||||
|
||||
#. Any keys stored to the user session are prefixed with the plugin's name and do not clash with other plugins or
|
||||
core.
|
||||
|
||||
#. Any registered URLs are unlikely to clash with other plugins or future core URLs.
|
||||
|
||||
C. Security
|
||||
-----------
|
||||
|
||||
#. All important actions are logged to the :ref:`shared log storage <logging>` and a signal receiver is registered to
|
||||
provide a human-readable representation of the log entry.
|
||||
|
||||
#. All views require appropriate permissions and use the ``event_urls`` mechanism if appropriate.
|
||||
:ref:`Read more <customview>`
|
||||
|
||||
#. Any session data for customers is stored in the cart session system if appropriate.
|
||||
|
||||
#. If the plugin is a payment provider:
|
||||
|
||||
#. No credit card numbers may be stored within pretix.
|
||||
|
||||
#. A notification/webhook system is implemented to notify pretix of any refunds.
|
||||
|
||||
#. If such a webhook system is implemented, contents of incoming webhooks are either verified using a cryptographic
|
||||
signature or are not being trusted and all data is fetched from an API instead.
|
||||
|
||||
D. Privacy
|
||||
----------
|
||||
|
||||
#. No personal data is stored that is not required for the plugin's functionality.
|
||||
|
||||
#. For any personal data that is saved to the database, an appropriate :ref:`data shredder <shredder>` is provided
|
||||
that offers the data for download and then removes it from the database (including log entries).
|
||||
|
||||
E. Internationalization
|
||||
-----------------------
|
||||
|
||||
#. All user-facing strings in templates, Python code, and templates are wrapped in `gettext calls`_.
|
||||
|
||||
#. No languages, time zones, date formats, or time formats are hardcoded.
|
||||
|
||||
#. Installing the plugin automatically compiles ``.po`` files to ``.mo`` files. This is fulfilled automatically if
|
||||
you use the ``setup.py`` file form our plugin cookiecutter.
|
||||
|
||||
F. Functionality
|
||||
----------------
|
||||
|
||||
#. If the plugin adds any database models or relationships from the settings storage to database models, it registers
|
||||
a receiver to the :py:attr:`pretix.base.signals.event_copy_data` or :py:attr:`pretix.base.signals.item_copy_data`
|
||||
signals.
|
||||
|
||||
#. If the plugin is a payment provider:
|
||||
|
||||
#. A webhook-like system is implemented if payment confirmations are not sent instantly.
|
||||
|
||||
#. Refunds are implemented, if possible.
|
||||
|
||||
#. In case of overpayment or external refunds, a "required action" is created to notify the event organizer.
|
||||
|
||||
#. If the plugin adds steps to the checkout process, it has been tested in combination with the pretix widget.
|
||||
|
||||
G. Code quality
|
||||
---------------
|
||||
|
||||
#. `isort`_ and `flake8`_ are used to ensure consistent code styling.
|
||||
|
||||
#. Unit tests are provided for important pieces of business logic.
|
||||
|
||||
#. Functional tests are provided for important interface parts.
|
||||
|
||||
#. Tests are provided to check that permission checks are working.
|
||||
|
||||
#. Continuous Integration is set up to check that tests are passing and styling is consistent.
|
||||
|
||||
H. Specific to pretix.eu
|
||||
------------------------
|
||||
|
||||
#. pretix.eu integrates the data stored by this plugin with its data report features.
|
||||
|
||||
#. pretix.eu integrates this plugin in its generated privacy statements, if necessary.
|
||||
|
||||
|
||||
.. _isort: https://www.google.de/search?q=isort&oq=isort&aqs=chrome..69i57j0j69i59j69i60l2j69i59.599j0j4&sourceid=chrome&ie=UTF-8
|
||||
.. _flake8: http://flake8.pycqa.org/en/latest/
|
||||
.. _gettext calls: https://docs.djangoproject.com/en/2.0/topics/i18n/translation/
|
||||
.. _dispatch_uid: https://docs.djangoproject.com/en/2.0/topics/signals/#django.dispatch.Signal.connect
|
||||
94
doc/development/api/shredder.rst
Normal file
@@ -0,0 +1,94 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
.. _`shredder`:
|
||||
|
||||
Writing a data shredder
|
||||
=======================
|
||||
|
||||
If your plugin adds the ability to store personal data within pretix, you should also implement a "data shredder"
|
||||
to anonymize or pseudonymize the data later.
|
||||
|
||||
Shredder registration
|
||||
---------------------
|
||||
|
||||
The data shredder API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available data shredders. Your plugin
|
||||
should listen for this signal and return the subclass of ``pretix.base.shredder.BaseDataShredder``
|
||||
that we'll provide in this plugin:
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_data_shredders
|
||||
|
||||
|
||||
@receiver(register_data_shredders, dispatch_uid="custom_data_shredders")
|
||||
def register_shredder(sender, **kwargs):
|
||||
return [
|
||||
PluginDataShredder,
|
||||
]
|
||||
|
||||
The shredder class
|
||||
------------------
|
||||
|
||||
.. class:: pretix.base.shredder.BaseDataShredder
|
||||
|
||||
The central object of each invoice renderer is the subclass of ``BaseInvoiceRenderer``.
|
||||
|
||||
.. py:attribute:: BaseInvoiceRenderer.event
|
||||
|
||||
The default constructor sets this property to the event we are currently
|
||||
working for.
|
||||
|
||||
.. autoattribute:: identifier
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: verbose_name
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: description
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. automethod:: generate_files
|
||||
|
||||
.. automethod:: shred_data
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
For example, the core data shredder responsible for removing invoice address information including their history
|
||||
looks like this:
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
class InvoiceAddressShredder(BaseDataShredder):
|
||||
verbose_name = _('Invoice addresses')
|
||||
identifier = 'invoice_addresses'
|
||||
description = _('This will remove all invoice addresses from orders, '
|
||||
'as well as logged changes to them.')
|
||||
|
||||
def generate_files(self) -> List[Tuple[str, str, str]]:
|
||||
yield 'invoice-addresses.json', 'application/json', json.dumps({
|
||||
ia.order.code: InvoiceAdddressSerializer(ia).data
|
||||
for ia in InvoiceAddress.objects.filter(order__event=self.event)
|
||||
}, indent=4)
|
||||
|
||||
@transaction.atomic
|
||||
def shred_data(self):
|
||||
InvoiceAddress.objects.filter(order__event=self.event).delete()
|
||||
|
||||
for le in self.event.logentry_set.filter(action_type="pretix.event.order.modified"):
|
||||
d = le.parsed_data
|
||||
if 'invoice_data' in d and not isinstance(d['invoice_data'], bool):
|
||||
for field in d['invoice_data']:
|
||||
if d['invoice_data'][field]:
|
||||
d['invoice_data'][field] = '█'
|
||||
le.data = json.dumps(d)
|
||||
le.shredded = True
|
||||
le.save(update_fields=['data', 'shredded'])
|
||||
|
||||
@@ -58,6 +58,8 @@ The output class
|
||||
|
||||
.. autoattribute:: is_enabled
|
||||
|
||||
.. autoattribute:: multi_download_enabled
|
||||
|
||||
.. autoattribute:: settings_form_fields
|
||||
|
||||
.. automethod:: settings_content_render
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
Implementation concepts
|
||||
=======================
|
||||
|
||||
Basic terminology
|
||||
-----------------
|
||||
Concepts and Terminology
|
||||
========================
|
||||
|
||||
The components
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The project pretix is split into several components. The main three of them are:
|
||||
The project pretix is split into several components. The main components are:
|
||||
|
||||
**base**
|
||||
This 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.
|
||||
several utilities which are used by multiple other components and important parts of
|
||||
the business logic.
|
||||
|
||||
**control**
|
||||
This is the web-based backend software which allows organizers to
|
||||
@@ -20,7 +18,13 @@ The project pretix is split into several components. The main three of them are:
|
||||
|
||||
**presale**
|
||||
This is the ticket-shop itself, containing all of the parts visible to the
|
||||
end user.
|
||||
end user. Also called "frontend" in parts of this documentation.
|
||||
|
||||
**api**
|
||||
A RESTful API exposed to integrate with third-party software.
|
||||
|
||||
**plugins**
|
||||
A set of pretix plugins that ship bundled with pretix.
|
||||
|
||||
Users and events
|
||||
^^^^^^^^^^^^^^^^
|
||||
@@ -55,12 +59,13 @@ If an item is assigned to multiple quotas, it can only be bought if *all of them
|
||||
If multiple items are assigned to the same quota, the quota will be counted as sold out as soon as the
|
||||
*sum* of the two items exceeds the quota limit.
|
||||
|
||||
The availability of a quota is currently calculated by substracting the following numbers from the quota
|
||||
The availability of a quota is currently calculated by subtracting the following numbers from the quota
|
||||
limit:
|
||||
|
||||
* The number of orders placed for an item that are either already paid or within their granted payment period
|
||||
* The number of non-expired items currently in the shopping cart of users
|
||||
* The number of vouchers defined as "quota blocking" (see blow)
|
||||
* The number of people on the waiting list
|
||||
|
||||
The quota system tries very hard to be as friendly as possible to your event attendees while still making sure
|
||||
your limit is never exceeded. For example, when the payment period of an order expires without the order being
|
||||
|
||||
@@ -77,6 +77,6 @@ Attribution
|
||||
-----------
|
||||
|
||||
This Code of Conduct is adapted from the `Contributor Covenant`_, version 1.4,
|
||||
available at http://contributor-covenant.org/version/1/4/
|
||||
available at https://www.contributor-covenant.org/version/1/4/
|
||||
|
||||
.. _Contributor Covenant: http://contributor-covenant.org
|
||||
.. _Contributor Covenant: https://www.contributor-covenant.org
|
||||
|
||||
@@ -9,7 +9,8 @@ constructive and friendly feedback on your changes.
|
||||
First of all, you'll need pretix running locally on your machine. Head over to :ref:`devsetup` to learn how to do this.
|
||||
If you run into any problems on your way, please do not hesitate to ask us anytime!
|
||||
|
||||
Please note that we have a :ref:`coc` in place that applies to all communication around the project.
|
||||
Please note that we bound ourselves to a :ref:`coc` that applies to all communication around the project. You can be
|
||||
assured that we will not tolerate any form of harassment.
|
||||
|
||||
Sending a patch
|
||||
---------------
|
||||
@@ -18,8 +19,9 @@ If you improved pretix in any way, we'd be very happy if you contribute it
|
||||
back to the main code base! The easiest way to do so is to `create a pull request`_
|
||||
on our `GitHub repository`_.
|
||||
|
||||
Before you do so, please `squash all your changes`_ into one single commit. Please
|
||||
use the test suite to check whether your changes break any existing features and run
|
||||
We recommend that you create a feature branch for every issue you work on so the changes can
|
||||
be reviewed individually.
|
||||
Please use the test suite to check whether your changes break any existing features and run
|
||||
the code style checks to confirm you are consistent with pretix's coding style. You'll
|
||||
find instructions on this in the :ref:`checksandtests` section of the development setup guide.
|
||||
|
||||
@@ -34,4 +36,3 @@ Again: If you get stuck, do not hesitate to contact any of us, or Raphael person
|
||||
|
||||
.. _create a pull request: https://help.github.com/articles/creating-a-pull-request/
|
||||
.. _GitHub repository: https://github.com/pretix/pretix
|
||||
.. _squash all your changes: https://davidwalsh.name/squash-commits-git
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Contribution guide
|
||||
==================
|
||||
Contributing to pretix
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
Coding style
|
||||
============
|
||||
Coding style and quality
|
||||
========================
|
||||
|
||||
Python code
|
||||
-----------
|
||||
* Basically, we want all python code to follow the `PEP 8`_ standard. There are a few exceptions where
|
||||
we see things differently or just aren't that strict. The ``setup.cfg`` file in the project's source
|
||||
folder contains definitions that allow `flake8`_ to check for violations automatically. See :ref:`checksandtests`
|
||||
for more information. Use four spaces for indentation.
|
||||
|
||||
* Basically: Follow `PEP 8`_.
|
||||
* We sort our imports by a certain schema, but you don't have to do this by hand. Again, ``setup.cfg`` contains
|
||||
some definitions that allow the command ``isort -rc <directory>`` to automatically sort the imports in your source
|
||||
files.
|
||||
|
||||
Use `flake8`_ to check for conformance problems. The project includes a setup.cfg file
|
||||
with a default configuration for flake8 that excludes migrations and other non-relevant
|
||||
code parts. It also silences a few checks, e.g. ``N802`` (function names should be lowercase)
|
||||
and increases the maximum line length to more than 79 characters. **However** you should
|
||||
still name all your functions lowercase [#f1]_ and keep your lines short when possible.
|
||||
* For templates and models, please take a look at the `Django Coding Style`_. We like Django's `class-based views`_ and
|
||||
kindly ask you to use them where appropriate.
|
||||
|
||||
* Our build server will reject all code violating other flake8 checks than the following:
|
||||
* Please remember to always mark all strings ever displayed to any user for `translation`_.
|
||||
|
||||
* E123: closing bracket does not match indentation of opening bracket’s line
|
||||
* F403: ``from module import *`` used; unable to detect undefined names
|
||||
* F401: module imported but unused
|
||||
* N802: function names should be lowercase
|
||||
* We expect all new code to come with proper tests. When writing new tests, please write them using `pytest-style`_
|
||||
test functions and raw ``assert`` statements. Use `fixtures`_ to prevent repetitive code. Some old parts of pretix'
|
||||
test suite are in the style of Python's unit test module. If you extend those files, you might continue in this style,
|
||||
but please use pytest style for any new test files.
|
||||
|
||||
So please make sure that you *always* follow all other rules and break these rules *only when
|
||||
it makes sense*.
|
||||
|
||||
* Use ``isort -rc pretix`` in the source directory to order your imports.
|
||||
|
||||
* Indent your code with four spaces.
|
||||
|
||||
* For templates and models, follow the `Django Coding Style`_.
|
||||
|
||||
* Use Django's class-based views
|
||||
|
||||
* Always mark all strings ever displayed to any user for translation.
|
||||
* Please keep the first line of your commit messages short. When referencing an issue, please phrase it like
|
||||
``Fix #123 -- Problems with order creation`` or ``Refs #123 -- Fix this part of that bug``.
|
||||
|
||||
|
||||
.. _PEP 8: http://legacy.python.org/dev/peps/pep-0008/
|
||||
.. _PEP 8: https://legacy.python.org/dev/peps/pep-0008/
|
||||
.. _flake8: https://pypi.python.org/pypi/flake8
|
||||
.. _Django Coding Style: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/
|
||||
.. [#f1] But Python's very own ``unittest`` module forces us to use ``setUp`` as a method name...
|
||||
.. _translation: https://docs.djangoproject.com/en/1.11/topics/i18n/translation/
|
||||
.. _class-based views: https://docs.djangoproject.com/en/1.11/topics/class-based-views/
|
||||
.. _pytest-style: https://docs.pytest.org/en/latest/assert.html
|
||||
.. _fixtures: https://docs.pytest.org/en/latest/fixture.html
|
||||
|
||||
@@ -14,7 +14,7 @@ Implementing a task
|
||||
A common pattern for implementing asynchronous tasks can be seen a lot in ``pretix.base.services``
|
||||
and looks like this::
|
||||
|
||||
from pretix.celery import app
|
||||
from pretix.celery_app import app
|
||||
|
||||
@app.task
|
||||
def my_task(argument1, argument2):
|
||||
|
||||
@@ -2,6 +2,9 @@ Sending Email
|
||||
=============
|
||||
|
||||
pretix allows event organizers to configure how they want to send emails to their users in multiple ways.
|
||||
Therefore, all emails should be sent through the following function:
|
||||
Therefore, all emails should be sent through the following function.
|
||||
|
||||
If the email you send is related to an order, you should also take a look at the
|
||||
:py:meth:`~pretix.base.models.Order.send_mail` of the order model.
|
||||
|
||||
.. autofunction:: pretix.base.services.mail.mail
|
||||
|
||||
@@ -16,4 +16,5 @@ Contents:
|
||||
settings
|
||||
background
|
||||
email
|
||||
permissions
|
||||
logging
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
Logging
|
||||
=======
|
||||
Logging and notifications
|
||||
=========================
|
||||
|
||||
As pretix is handling monetary transactions, we are very careful to make it possible to review all changes
|
||||
in the system that lead to the current state.
|
||||
|
||||
.. _`logging`:
|
||||
|
||||
Logging changes
|
||||
---------------
|
||||
|
||||
@@ -19,7 +21,7 @@ To actually log an action, you can just call the ``log_action`` method on your o
|
||||
order.log_action('pretix.event.order.canceled', user=user, data={})
|
||||
|
||||
The positional ``action`` argument should represent the type of action and should be globally unique, we
|
||||
recomment do prefix it with your packagename, e.g. ``paypal.payment.rejected``. The ``user`` argument is
|
||||
recommend to prefix it with your package name, e.g. ``paypal.payment.rejected``. The ``user`` argument is
|
||||
optional and may contain the user who performed the action. The optional ``data`` argument can contain
|
||||
additional information about this action.
|
||||
|
||||
@@ -81,6 +83,61 @@ implementation could look like::
|
||||
if logentry.action_type in plains:
|
||||
return plains[logentry.action_type]
|
||||
|
||||
Sending notifications
|
||||
---------------------
|
||||
|
||||
If you think that the logged information might be important or urgent enough to send out a notification to interested
|
||||
organizers. In this case, you should listen for the :py:attr:`pretix.base.signals.register_notification_types` signal
|
||||
to register a notification type::
|
||||
|
||||
@receiver(register_notification_types)
|
||||
def register_my_notification_types(sender, **kwargs):
|
||||
return [MyNotificationType(sender)]
|
||||
|
||||
Note that this event is different than other events send out by pretix: ``sender`` may be an event or ``None``. The
|
||||
latter case is required to let the user define global notification preferences for all events.
|
||||
|
||||
You also need to implement a custom class that specifies how notifications should be handled for your notification type.
|
||||
You should subclass the base ``NotificationType`` class and implement all its members:
|
||||
|
||||
.. autoclass:: pretix.base.notifications.NotificationType
|
||||
:members: action_type, verbose_name, required_permission, build_notification
|
||||
|
||||
A simple implementation could look like this::
|
||||
|
||||
class MyNotificationType(NotificationType):
|
||||
required_permission = "can_view_orders"
|
||||
action_type = "pretix.event.order.paid"
|
||||
verbose_name = _("Order has been paid")
|
||||
|
||||
def build_notification(self, logentry: LogEntry):
|
||||
order = logentry.content_object
|
||||
|
||||
order_url = build_absolute_uri(
|
||||
'control:event.order',
|
||||
kwargs={
|
||||
'organizer': logentry.event.organizer.slug,
|
||||
'event': logentry.event.slug,
|
||||
'code': order.code
|
||||
}
|
||||
)
|
||||
|
||||
n = Notification(
|
||||
event=logentry.event,
|
||||
title=_('Order {code} has been marked as paid').format(code=order.code),
|
||||
url=order_url
|
||||
)
|
||||
n.add_attribute(_('Order code'), order.code)
|
||||
n.add_action(_('View order details'), order_url)
|
||||
return n
|
||||
|
||||
As you can see, the relevant code is in the ``build_notification`` method that is supposed to create a ``Notification``
|
||||
method that has a title, description, URL, attributes, and actions. The full definition of ``Notification`` is the
|
||||
following:
|
||||
|
||||
.. autoclass:: pretix.base.notifications.Notification
|
||||
:members: add_action, add_attribute
|
||||
|
||||
|
||||
Logging technical information
|
||||
-----------------------------
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
.. spelling:: answ contrib
|
||||
|
||||
Data model
|
||||
==========
|
||||
|
||||
@@ -20,18 +22,30 @@ Organizers and events
|
||||
.. autoclass:: pretix.base.models.Organizer
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.OrganizerPermission
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Event
|
||||
:members: get_date_from_display, get_time_from_display, get_date_to_display, get_date_range_display, presale_has_ended, presale_is_running, cache, lock, get_plugins, get_mail_backend, payment_term_last, get_payment_providers, get_invoice_renderers, active_subevents, invoice_renderer, settings
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEvent
|
||||
:members: get_date_from_display, get_time_from_display, get_date_to_display, get_date_range_display, presale_has_ended, presale_is_running
|
||||
|
||||
.. autoclass:: pretix.base.models.Team
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.EventPermission
|
||||
.. autoclass:: pretix.base.models.TeamAPIToken
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.RequiredAction
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.EventMetaProperty
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.EventMetaValue
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEventMetaValue
|
||||
:members:
|
||||
|
||||
|
||||
Items
|
||||
-----
|
||||
@@ -45,6 +59,15 @@ Items
|
||||
.. autoclass:: pretix.base.models.ItemVariation
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEventItem
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEventItemVariation
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.ItemAddOn
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Question
|
||||
:members:
|
||||
|
||||
@@ -63,11 +86,20 @@ Carts and Orders
|
||||
.. autoclass:: pretix.base.models.OrderPosition
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.OrderFee
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.OrderPayment
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.OrderRefund
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.CartPosition
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.QuestionAnswer
|
||||
:members:
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Checkin
|
||||
:members:
|
||||
@@ -92,5 +124,3 @@ Vouchers
|
||||
|
||||
.. autoclass:: pretix.base.models.Voucher
|
||||
:members:
|
||||
|
||||
.. _cleanerversion: https://github.com/swisscom/cleanerversion
|
||||
|
||||
194
doc/development/implementation/permissions.rst
Normal file
@@ -0,0 +1,194 @@
|
||||
Permissions
|
||||
===========
|
||||
|
||||
pretix uses a fine-grained permission system to control who is allowed to control what parts of the system.
|
||||
The central concept here is the concept of *Teams*. You can read more on `configuring teams and permissions <user-teams>`_
|
||||
and the :class:`pretix.base.models.Team` model in the respective parts of the documentation. The basic digest is:
|
||||
An organizer account can have any number of teams, and any number of users can be part of a team. A team can be
|
||||
assigned a set of permissions and connected to some or all of the events of the organizer.
|
||||
|
||||
A second way to access pretix is via the REST API, which allows authentication via tokens that are bound to a team,
|
||||
but not to a user. You can read more at :class:`pretix.base.models.TeamAPIToken`. This page will show you how to
|
||||
work with permissions in plugins and within the pretix code base.
|
||||
|
||||
Requiring permissions for a view
|
||||
--------------------------------
|
||||
|
||||
pretix provides a number of useful mixins and decorators that allow you to specify that a user needs a certain
|
||||
permission level to access a view::
|
||||
|
||||
from pretix.control.permissions import (
|
||||
OrganizerPermissionRequiredMixin, organizer_permission_required
|
||||
)
|
||||
|
||||
|
||||
class MyOrgaView(OrganizerPermissionRequiredMixin, View):
|
||||
permission = 'can_change_organizer_settings'
|
||||
# Only users with the permission ``can_change_organizer_settings`` on
|
||||
# this organizer can access this
|
||||
|
||||
|
||||
class MyOtherOrgaView(OrganizerPermissionRequiredMixin, View):
|
||||
permission = None
|
||||
# Only users with *any* permission on this organizer can access this
|
||||
|
||||
|
||||
@organizer_permission_required('can_change_organizer_settings')
|
||||
def my_orga_view(request, organizer, **kwargs):
|
||||
# Only users with the permission ``can_change_organizer_settings`` on
|
||||
# this organizer can access this
|
||||
|
||||
|
||||
@organizer_permission_required()
|
||||
def my_other_orga_view(request, organizer, **kwargs):
|
||||
# Only users with *any* permission on this organizer can access this
|
||||
|
||||
|
||||
Of course, the same is available on event level::
|
||||
|
||||
from pretix.control.permissions import (
|
||||
EventPermissionRequiredMixin, event_permission_required
|
||||
)
|
||||
|
||||
|
||||
class MyEventView(EventPermissionRequiredMixin, View):
|
||||
permission = 'can_change_event_settings'
|
||||
# Only users with the permission ``can_change_event_settings`` on
|
||||
# this event can access this
|
||||
|
||||
|
||||
class MyOtherEventView(EventPermissionRequiredMixin, View):
|
||||
permission = None
|
||||
# Only users with *any* permission on this event can access this
|
||||
|
||||
|
||||
@event_permission_required('can_change_event_settings')
|
||||
def my_event_view(request, organizer, **kwargs):
|
||||
# Only users with the permission ``can_change_event_settings`` on
|
||||
# this event can access this
|
||||
|
||||
|
||||
@event_permission_required()
|
||||
def my_other_event_view(request, organizer, **kwargs):
|
||||
# Only users with *any* permission on this event can access this
|
||||
|
||||
You can also require that this view is only accessible by system administrators with an active "admin session"
|
||||
(see below for what this means)::
|
||||
|
||||
from pretix.control.permissions import (
|
||||
AdministratorPermissionRequiredMixin, administrator_permission_required
|
||||
)
|
||||
|
||||
|
||||
class MyGlobalView(AdministratorPermissionRequiredMixin, View):
|
||||
# ...
|
||||
|
||||
|
||||
@administrator_permission_required
|
||||
def my_global_view(request, organizer, **kwargs):
|
||||
# ...
|
||||
|
||||
In rare cases it might also be useful to expose a feature only to people who have a staff account but do not
|
||||
necessarily have an active admin session::
|
||||
|
||||
from pretix.control.permissions import (
|
||||
StaffMemberRequiredMixin, staff_member_required
|
||||
)
|
||||
|
||||
|
||||
class MyGlobalView(StaffMemberRequiredMixin, View):
|
||||
# ...
|
||||
|
||||
|
||||
@staff_member_required
|
||||
def my_global_view(request, organizer, **kwargs):
|
||||
# ...
|
||||
|
||||
|
||||
|
||||
Requiring permissions in the REST API
|
||||
-------------------------------------
|
||||
|
||||
When creating your own ``viewset`` using Django REST framework, you just need to set the ``permission`` attribute
|
||||
and pretix will check it automatically for you::
|
||||
|
||||
class MyModelViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
permission = 'can_view_orders'
|
||||
|
||||
Checking permission in code
|
||||
---------------------------
|
||||
|
||||
If you need to work with permissions manually, there are a couple of useful helper methods on the :class:`pretix.base.models.Event`,
|
||||
:class:`pretix.base.models.User` and :class:`pretix.base.models.TeamAPIToken` classes. Here's a quick overview.
|
||||
|
||||
Return all users that are in any team that is connected to this event::
|
||||
|
||||
>>> event.get_users_with_any_permission()
|
||||
<QuerySet: …>
|
||||
|
||||
Return all users that are in a team with a specific permission for this event::
|
||||
|
||||
>>> event.get_users_with_permission('can_change_event_settings')
|
||||
<QuerySet: …>
|
||||
|
||||
Determine if a user has a certain permission for a specific event::
|
||||
|
||||
>>> user.has_event_permission(organizer, event, 'can_change_event_settings', request=request)
|
||||
True
|
||||
|
||||
Determine if a user has any permission for a specific event::
|
||||
|
||||
>>> user.has_event_permission(organizer, event, request=request)
|
||||
True
|
||||
|
||||
In the two previous commands, the ``request`` argument is optional, but required to support staff sessions (see below).
|
||||
|
||||
The same method exists for organizer-level permissions::
|
||||
|
||||
>>> user.has_organizer_permission(organizer, 'can_change_event_settings', request=request)
|
||||
True
|
||||
|
||||
Sometimes, it might be more useful to get the set of permissions at once::
|
||||
|
||||
>>> user.get_event_permission_set(organizer, event)
|
||||
{'can_change_event_settings', 'can_view_orders', 'can_change_orders'}
|
||||
|
||||
>>> user.get_organizer_permission_set(organizer, event)
|
||||
{'can_change_organizer_settings', 'can_create_events'}
|
||||
|
||||
Within a view on the ``/control`` subpath, the results of these two methods are already available in the
|
||||
``request.eventpermset`` and ``request.orgapermset`` properties. This makes it convenient to query them in templates::
|
||||
|
||||
{% if "can_change_orders" in request.eventpermset %}
|
||||
…
|
||||
{% endif %}
|
||||
|
||||
You can also do the reverse to get any events a user has access to::
|
||||
|
||||
>>> user.get_events_with_permission('can_change_event_settings', request=request)
|
||||
<QuerySet: …>
|
||||
|
||||
>>> user.get_events_with_any_permission(request=request)
|
||||
<QuerySet: …>
|
||||
|
||||
Most of these methods work identically on :class:`pretix.base.models.TeamAPIToken`.
|
||||
|
||||
Staff sessions
|
||||
--------------
|
||||
|
||||
.. versionchanged:: 1.14
|
||||
|
||||
In 1.14, the ``User.is_superuser`` attribute has been deprecated and statically set to return ``False``. Staff
|
||||
sessions have been newly introduced.
|
||||
|
||||
System administrators of a pretix instance are identified by the ``is_staff`` attribute on the user model. By default,
|
||||
the regular permission rules apply for users with ``is_staff = True``. The only difference is that such users can
|
||||
temporarily turn on "staff mode" via a button in the user interface that grants them **all permissions** as long as
|
||||
staff mode is active. You can check if a user is in staff mode using their session key:
|
||||
|
||||
>>> user.has_active_staff_session(request.session.session_key)
|
||||
False
|
||||
|
||||
Staff mode has a hard time limit and during staff mode, a middleware will log all requests made by that user. Later,
|
||||
the user is able to also save a message to comment on what they did in their administrative session. This feature is
|
||||
intended to help compliance with data protection rules as imposed e.g. by GDPR.
|
||||
@@ -2,7 +2,10 @@ Settings storage
|
||||
================
|
||||
|
||||
pretix is highly configurable and therefore needs to store a lot of per-event and per-organizer settings.
|
||||
Those settings are stored in the database and accessed through a ``SettingsProxy`` instance. You can obtain
|
||||
For this purpose, we use `django-hierarkey`_ which started out as part of pretix and then got refactored into
|
||||
its own library. It has a comprehensive `documentation`_ which you should read if you work with settings in pretix.
|
||||
|
||||
The settings are stored in the database and accessed through a ``HierarkeyProxy`` instance. You can obtain
|
||||
such an instance from any event or organizer model instance by just accessing ``event.settings`` or
|
||||
``organizer.settings``, respectively.
|
||||
|
||||
@@ -17,12 +20,10 @@ includes serializers for serializing the following types:
|
||||
|
||||
In code, we recommend to always use the ``.get()`` method on the settings object to access a value, but for
|
||||
convenience in templates you can also access settings values at ``settings[name]`` and ``settings.name``.
|
||||
|
||||
.. autoclass:: pretix.base.settings.SettingsProxy
|
||||
:members: get, set, delete, freeze
|
||||
See the hierarkey `documentation`_ for more information.
|
||||
|
||||
To avoid naming conflicts, plugins are requested to prefix all settings they use with the name of the plugin
|
||||
or something unique, e.g. ``payment.paypal.api_key``. To reduce redundant typing of this prefix, we provide
|
||||
or something unique, e.g. ``payment_paypal_api_key``. To reduce redundant typing of this prefix, we provide
|
||||
another helper class:
|
||||
|
||||
.. autoclass:: pretix.base.settings.SettingsSandbox
|
||||
@@ -33,10 +34,10 @@ you will just be passed a sandbox object with a prefix generated from your provi
|
||||
Forms
|
||||
-----
|
||||
|
||||
We also provide a base class for forms that allow the modification of settings:
|
||||
Hierarkey also provides a base class for forms that allow the modification of settings. pretix contains a
|
||||
subclass that also adds support for internationalized fields:
|
||||
|
||||
.. autoclass:: pretix.base.forms.SettingsForm
|
||||
:members: save
|
||||
|
||||
You can simply use it like this::
|
||||
|
||||
@@ -51,3 +52,17 @@ You can simply use it like this::
|
||||
help_text=_("The number of days after placing an order the user has to pay to "
|
||||
"preserve his reservation."),
|
||||
)
|
||||
|
||||
Defaults in plugins
|
||||
-------------------
|
||||
|
||||
Plugins can add custom hardcoded defaults in the following way::
|
||||
|
||||
from pretix.base.settings import settings_hierarkey
|
||||
|
||||
settings_hierarkey.add_default('key', 'value', type)
|
||||
|
||||
Make sure that you include this code in a module that is imported at app loading time.
|
||||
|
||||
.. _django-hierarkey: https://github.com/raphaelm/django-hierarkey
|
||||
.. _documentation: https://django-hierarkey.readthedocs.io/en/latest/
|
||||
|
||||
@@ -67,7 +67,7 @@ available as ``plugins:sendmail:send``.
|
||||
Generating a URL for the frontend is a complicated task, because you need to know whether the event's
|
||||
organizer uses a custom URL or not and then generate the URL with a different domain and different
|
||||
arguments based on this information. pretix provides some helpers to make this easier. The first helper
|
||||
is a python method that emulates a behaviour similar to ``reverse``:
|
||||
is a python method that emulates a behavior similar to ``reverse``:
|
||||
|
||||
.. autofunction:: pretix.multidomain.urlreverse.eventreverse
|
||||
|
||||
@@ -82,5 +82,5 @@ Implementation details
|
||||
----------------------
|
||||
|
||||
There are some other caveats when using a design like this, e.g. you have to care about cookie domains
|
||||
and referer verification yourself. If you want to see how we built this, look into the ``pretix/multidomain/``
|
||||
and referrer verification yourself. If you want to see how we built this, look into the ``pretix/multidomain/``
|
||||
sub-tree.
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
Developer documentation
|
||||
=======================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
concepts
|
||||
setup
|
||||
structure
|
||||
contribution/index
|
||||
implementation/index
|
||||
translation/index
|
||||
api/index
|
||||
|
||||
.. TODO::
|
||||
Document settings objects, ItemVariation objects, form fields.
|
||||
structure
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
.. _`devsetup`:
|
||||
|
||||
The development setup
|
||||
=====================
|
||||
Development setup
|
||||
=================
|
||||
|
||||
This tutorial helps you to get started hacking with pretix on your own computer. You need this to
|
||||
be able to contribute to pretix, but it might also be helpful if you want to write your own plugins.
|
||||
If you want to install pretix on a server for actual usage, go to the :ref:`admindocs` instead.
|
||||
|
||||
Obtain a copy of the source code
|
||||
--------------------------------
|
||||
@@ -12,9 +16,10 @@ You can just clone our git repository::
|
||||
|
||||
External Dependencies
|
||||
---------------------
|
||||
* Python 3.4 or newer
|
||||
Your should install the following on your system:
|
||||
|
||||
* Python 3.5 or newer
|
||||
* ``pip`` for Python 3 (Debian package: ``python3-pip``)
|
||||
* ``pyvenv`` for Python 3 (Debian package: ``python3-venv``)
|
||||
* ``python-dev`` for Python 3 (Debian package: ``python3-dev``)
|
||||
* ``libffi`` (Debian package: ``libffi-dev``)
|
||||
* ``libssl`` (Debian package: ``libssl-dev``)
|
||||
@@ -31,7 +36,7 @@ Please execute ``python -V`` or ``python3 -V`` to make sure you have Python 3.4
|
||||
execute ``pip3 -V`` to check. Then use Python's internal tools to create a virtual
|
||||
environment and activate it for your current session::
|
||||
|
||||
pyvenv env
|
||||
python3 -m venv env
|
||||
source env/bin/activate
|
||||
|
||||
You should now see a ``(env)`` prepended to your shell prompt. You have to do this
|
||||
@@ -40,7 +45,7 @@ automatically). If you are working on Ubuntu or Debian, we strongly recommend up
|
||||
your pip and setuptools installation inside the virtual environment, otherwise some of
|
||||
the dependencies might fail::
|
||||
|
||||
pip3 install -U pip setuptools==28.6.1
|
||||
pip3 install -U pip setuptools
|
||||
|
||||
Working with the code
|
||||
---------------------
|
||||
@@ -49,10 +54,6 @@ The first thing you need are all the main application's dependencies::
|
||||
cd src/
|
||||
pip3 install -r requirements.txt -r requirements/dev.txt
|
||||
|
||||
If you are working with Python 3.4, you will also need (you can skip this for Python 3.5)::
|
||||
|
||||
pip3 install -r requirements/py34.txt
|
||||
|
||||
Next, you need to copy the SCSS files from the source folder to the STATIC_ROOT directory::
|
||||
|
||||
python manage.py collectstatic --noinput
|
||||
@@ -81,17 +82,28 @@ and head to http://localhost:8000/
|
||||
|
||||
As we did not implement an overall front page yet, you need to go directly to
|
||||
http://localhost:8000/control/ for the admin view or, if you imported the test
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2017/
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2019/
|
||||
|
||||
.. note:: If you want the development server to listen on a different interface or
|
||||
port (for example because you develop on `pretixdroid`_), you can check
|
||||
`Django's documentation`_ for more options.
|
||||
|
||||
.. _`checksandtests`:
|
||||
|
||||
Code checks and unit tests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Before you check in your code into git, always run the static checkers and unit tests::
|
||||
Before you check in your code into git, always run static checkers and linters. If any of these commands fail,
|
||||
your pull request will not be merged into pretix. If you have trouble figuring out *why* they fail, create your
|
||||
pull request nevertheless and ask us for help, we are happy to assist you.
|
||||
|
||||
Execute the following commands to check for code style errors::
|
||||
|
||||
flake8 .
|
||||
isort -c -rc .
|
||||
python manage.py check
|
||||
|
||||
Execute the following command to run pretix' test suite (might take a couple of minutes)::
|
||||
|
||||
py.test
|
||||
|
||||
.. note:: If you have multiple CPU cores and want to speed up the test suite, you can install the python
|
||||
@@ -99,14 +111,24 @@ Before you check in your code into git, always run the static checkers and unit
|
||||
``NUM`` being the number of threads you want to use.
|
||||
|
||||
It is a good idea to put this command into your git hook ``.git/hooks/pre-commit``,
|
||||
for example::
|
||||
for example, to check for any errors in any staged files when committing::
|
||||
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
cd $GIT_DIR/../src
|
||||
source ../env/bin/activate
|
||||
flake8 --ignore=E123,E128,F403,F401,N802,W503 .
|
||||
export GIT_WORK_TREE=../
|
||||
export GIT_DIR=../.git
|
||||
source ../env/bin/activate # Adjust to however you activate your virtual environment
|
||||
for file in $(git diff --cached --name-only | grep -E '\.py$' | grep -Ev "migrations|mt940\.py|pretix/settings\.py|make_testdata\.py|testutils/settings\.py|tests/settings\.py|pretix/base/models/__init__\.py")
|
||||
do
|
||||
echo $file
|
||||
git show ":$file" | flake8 - --stdin-display-name="$file" || exit 1 # we only want to lint the staged changes, not any un-staged changes
|
||||
git show ":$file" | isort -df --check-only - | grep ERROR && exit 1 || true
|
||||
done
|
||||
|
||||
|
||||
|
||||
This keeps you from accidentally creating commits violating the style guide.
|
||||
|
||||
Working with mails
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
If you want to test anything regarding emails in your development setup, we recommend
|
||||
@@ -128,6 +150,10 @@ and update the ``*.po`` files accordingly::
|
||||
|
||||
make localegen
|
||||
|
||||
However, most of the time you don't need to care about this. Just create your pull request
|
||||
with functionality and English strings only, and we'll push the new translation strings
|
||||
to our translation platform after the merge.
|
||||
|
||||
To actually see pretix in your language, you have to compile the ``*.po`` files to their
|
||||
optimized binary ``*.mo`` counterparts::
|
||||
|
||||
@@ -147,4 +173,14 @@ To build the documentation, run the following command from the ``doc/`` director
|
||||
|
||||
make html
|
||||
|
||||
You will now find the generated documentation in the ``doc/_build/html/`` subdirectory.
|
||||
You will now find the generated documentation in the ``doc/_build/html/`` subdirectory. If you work
|
||||
with the documentation a lot, you might find it useful to use sphinx-autobuild::
|
||||
|
||||
pip3 install sphinx-autobuild
|
||||
sphinx-autobuild . _build/html -p 8081
|
||||
|
||||
Then, go to http://localhost:8081 for a version of the documentation that automatically re-builds
|
||||
whenever you change a source file.
|
||||
|
||||
.. _Django's documentation: https://docs.djangoproject.com/en/1.11/ref/django-admin/#runserver
|
||||
.. _pretixdroid: https://github.com/pretix/pretixdroid
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
Project structure
|
||||
=================
|
||||
|
||||
Python source code
|
||||
------------------
|
||||
Directory structure
|
||||
===================
|
||||
|
||||
All the source code lives in ``src/``, which has several subdirectories.
|
||||
|
||||
pretix/
|
||||
This directory contains nearly all source code.
|
||||
This directory contains nearly all source code that belongs to pretix.
|
||||
|
||||
base/
|
||||
This is the Django app containing all the models and methods which are
|
||||
@@ -19,57 +16,31 @@ pretix/
|
||||
presale/
|
||||
This is the Django app containing the front end for users buying tickets.
|
||||
|
||||
api/
|
||||
This is the Django app containing all views and serializers for pretix'
|
||||
:ref:`rest-api`.
|
||||
|
||||
helpers/
|
||||
Helpers contain a very few modules providing workarounds for low-level flaws in
|
||||
Django or installed 3rd-party packages.
|
||||
|
||||
locale/
|
||||
Contains translation file for pretix
|
||||
|
||||
multidomain/
|
||||
Additional code implementing our customized :ref:`URL handling <urlconf>`.
|
||||
|
||||
static/
|
||||
Contains all static files (CSS, JavaScript, images)
|
||||
static/
|
||||
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core
|
||||
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
|
||||
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
|
||||
|
||||
testutils/
|
||||
Contains helper methods that are useful to write the test suite for pretix or test
|
||||
suites for pretix plugins.
|
||||
|
||||
tests/
|
||||
This is the root directory for all test codes. It includes subdirectories ``base``,
|
||||
``control``, ``presale``, ``helpers`` and ``plugins`` to mirror the structure of the
|
||||
``pretix`` source code as well as ``testdummy``, which is a pretix plugin used during
|
||||
This is the root directory for all test codes. It includes subdirectories ``api``, ``base``,
|
||||
``control``, ``presale``, ``helpers`, ``multidomain`` and ``plugins`` to mirror the structure
|
||||
of the pretix source code as well as ``testdummy``, which is a pretix plugin used during
|
||||
testing.
|
||||
|
||||
Language files
|
||||
--------------
|
||||
The language files live in ``locale/*/LC_MESSAGES/``.
|
||||
|
||||
Static files
|
||||
------------
|
||||
|
||||
Sass source code
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
|
||||
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
|
||||
|
||||
pretix.control
|
||||
pretixcontrol has two main SCSS files, ``pretix/control/static/pretixcontrol/scss/main.scss`` and
|
||||
``pretix/control/static/pretixcontrol/scss/auth.scss``, importing everything else.
|
||||
|
||||
pretix.presale
|
||||
pretixpresale has one main SCSS files, ``pretix/control/static/pretix/presale/scss/main.scss``,
|
||||
importing everything else.
|
||||
|
||||
3rd-party assets
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Bootstrap
|
||||
Bootstrap lives vendored at ``static/bootstrap/``
|
||||
|
||||
Font Awesome
|
||||
Font Awesome lives vendored at ``static/fontawesome/``
|
||||
|
||||
jQuery
|
||||
jQuery lives as a single JavaScript file in ``static/jquery/js/``
|
||||
|
||||
jQuery plugin: Django formsets
|
||||
Our own modified version of `django-formset-js`_ is available as an independent
|
||||
django app and installed via ``pip``.
|
||||
|
||||
.. _django-formset-js: https://github.com/pretix/django-formset-js
|
||||
|
||||
BIN
doc/development/translation/img/weblate1.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
doc/development/translation/img/weblate2.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
doc/development/translation/img/weblate3.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
doc/development/translation/img/weblate4.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
doc/development/translation/img/weblate5.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
doc/development/translation/img/weblate6.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
88
doc/development/translation/index.rst
Normal file
@@ -0,0 +1,88 @@
|
||||
Translating pretix
|
||||
==================
|
||||
|
||||
pretix has been designed for multi-language capabilities from its start. Organizers can enter their event information
|
||||
in multiple languages at the same time. However, the software interface of pretix also needs to be translated for
|
||||
this to be useful.
|
||||
|
||||
Since we (the developers of pretix) only speak a very limited number of languages, we need help from the community
|
||||
to achieve this goal. To make translating pretix easy not only for software developers, we set up a translation
|
||||
platform at `translate.pretix.eu`_.
|
||||
|
||||
Official and inofficial languages
|
||||
---------------------------------
|
||||
|
||||
In the pretix project, there are three types of languages:
|
||||
|
||||
Official languages
|
||||
are translated and maintained by the core team behind pretix or as part of long-term partnerships. We are
|
||||
committed to keeping these translations up-to-date with new features or changes in pretix and try to offer
|
||||
support in this language.
|
||||
|
||||
Inofficial languages
|
||||
are contributed and maintained by the Community. We ship them with pretix so you can use them, but we can not
|
||||
guarantee that new or changed features in pretix will be translated in time.
|
||||
|
||||
Incubating languages
|
||||
are currently in the process of being translated. They can not yet be selected in pretix by end users on
|
||||
production installations and are only available in development mode for testing.
|
||||
|
||||
Please contact translate@pretix.eu if you think an incubated language should be promoted to an inofficial one or if
|
||||
you are interested in a partnership to make your language official.
|
||||
|
||||
The current translation status of various languages is:
|
||||
|
||||
.. image:: https://translate.pretix.eu/widgets/pretix/-/multi-blue.svg
|
||||
:target: https://translate.pretix.eu/engage/pretix/?utm_source=widget
|
||||
|
||||
|
||||
Using our translation platform
|
||||
------------------------------
|
||||
|
||||
If you visit `translate.pretix.eu`_ for the first time, it admittedly looks pretty bare.
|
||||
|
||||
.. image:: img/weblate1.png
|
||||
:class: screenshot
|
||||
|
||||
It gets better if you create an account, which you will need to contribute translations. Click on "Register" in the
|
||||
top-right corner to get started:
|
||||
|
||||
.. image:: img/weblate2.png
|
||||
:class: screenshot
|
||||
|
||||
You can either create an account or choose to log in with your GitHub account, whichever you like more.
|
||||
After creating and activating your account, we recommend that you change your profile and select which languages you
|
||||
can translate to and which languages you understand. You can find your profile settings by clicking on your name in
|
||||
the top-right corner.
|
||||
|
||||
.. image:: img/weblate3.png
|
||||
:class: screenshot
|
||||
|
||||
Going back to the dashboard by clicking on the logo in the top-left corner, you can select between different lists
|
||||
of translation projects. You can either filter by projects that already have a translation in your language, or you
|
||||
go to the `pretix project page`_ where you can select specific components.
|
||||
|
||||
.. note::
|
||||
|
||||
If you want to translate pretix to a new language that is not yet listed here, you are very welcome to do so!
|
||||
While you technically can add the language to the portal yourself, we ask you to drop us a short mail to
|
||||
translate@pretix.eu so we can add it to all components at once and also make it selectable in pretix itself.
|
||||
|
||||
.. image:: img/weblate4.png
|
||||
:class: screenshot
|
||||
|
||||
Once you selected a component of a language, you can start going through strings to translate. You can start of by
|
||||
clicking the "Strings needing action" line in this view:
|
||||
|
||||
.. image:: img/weblate5.png
|
||||
:class: screenshot
|
||||
|
||||
In the translate view, you can input your translation for a given source string. If you're unsure about your
|
||||
translation, you can also just "Suggest" it or mark it as "Needs editing". If you have no idea, just "Skip". If you
|
||||
scroll down, there is also a "Comments" section to discuss any questions with fellow translators or us developers.
|
||||
|
||||
.. image:: img/weblate6.png
|
||||
:class: screenshot
|
||||
|
||||
.. _translate.pretix.eu: https://translate.pretix.eu
|
||||
.. _pretix project page: https://translate.pretix.eu/projects/pretix/
|
||||
69
doc/images/logo-white.svg
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="254.15625"
|
||||
height="109.59375"
|
||||
viewBox="0 0 254.15625 109.59375"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="logo-white.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1364"
|
||||
inkscape:window-height="676"
|
||||
id="namedview7"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="56.462442"
|
||||
inkscape:cy="54.796875"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="72"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg5" />
|
||||
|
||||
id="svg2"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-277.78125,-568.75)">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate"
|
||||
d="m 20,20 v 34.09375 c 11.43679,0 20.71875,9.28196 20.71875,20.71875 C 40.71875,86.24928 31.43679,95.5 20,95.5 v 34.09375 h 146.6875 v -9.5 h 3 v 9.5 H 274.15625 V 95.5 c -0.0105,2e-5 -0.0208,0 -0.0312,0 -11.43678,0 -20.71875,-9.25072 -20.71875,-20.6875 0,-11.43679 9.28197,-20.71875 20.71875,-20.71875 0.0105,0 0.0208,-2e-5 0.0312,0 V 20 H 169.6875 v 9.09375 h -3 V 20 Z m 146.6875,16.09375 h 3 v 14 h -3 z m 41.44141,12.833984 c 2.79067,0 5.02343,1.92774 5.02343,4.3125 0,2.38476 -2.23276,4.363282 -5.02343,4.363282 -2.73994,0 -4.97266,-1.978522 -4.97266,-4.363282 0,-2.38476 2.23272,-4.3125 4.97266,-4.3125 z m -13.22852,4.210938 v 8.017578 h 3.95899 v 6.291016 h -3.95899 v 12.279296 c 0,2.02959 0.71015,2.791016 2.13086,2.791016 0.71035,0 1.06703,-0.10181 1.82813,-0.40625 v 5.935547 c -0.71036,0.40591 -2.38661,0.964844 -4.61915,0.964844 -6.13949,0 -8.98046,-3.753876 -8.98046,-8.472657 V 67.447266 h -2.8418 V 61.15625 h 2.8418 V 55.574219 Z M 166.6875,57.09375 h 3 v 14 h -3 z m -74.568359,3.554688 c 8.473509,0 14.207029,4.515688 14.207029,14.105468 0,8.62573 -5.02336,14.105469 -12.07617,14.105469 -1.72514,0 -3.147072,-0.20329 -3.857422,-0.40625 V 99.414062 H 80.751953 V 62.728516 c 2.58772,-1.21775 6.090268,-2.080081 11.367188,-2.080078 z m 49.863279,0 c 8.57499,0 12.63436,5.935363 12.12696,15.220703 l -15.93165,2.234375 c 0.60888,2.94289 2.18061,4.414062 5.68165,4.414062 3.24732,0 5.78445,-0.711556 7.30664,-1.472656 l 2.13086,5.886719 c -2.38476,1.16701 -5.58034,2.080078 -10.6543,2.080078 -8.93017,0 -13.64844,-6.037993 -13.64844,-14.257813 0,-8.21981 4.41329,-14.105468 12.98828,-14.105468 z m -17.92187,0.0059 c 0.8928,0.01358 1.82795,0.04496 2.80468,0.0957 l -1.67578,6.697266 c -1.77589,-0.86257 -3.50104,-0.913692 -4.76953,-0.457032 v 21.513672 h -9.64062 v -25.77539 c 2.79702,-1.376314 7.03166,-2.16926 13.28125,-2.074219 z m 79.24804,0.501953 h 9.64063 v 27.347656 h -9.64063 z m 13.23438,0 h 10.04687 l 3.29883,6.849609 h 0.10156 l 3.60157,-6.849609 h 8.98047 l -7.96485,12.632812 8.72656,14.714844 H 232.67969 L 229.17773,80.9434 h -0.10156 l -3.65234,7.560547 h -9.74219 l 8.57422,-14.105468 z m -74.9668,5.023438 c -2.84142,0 -4.41381,2.585948 -4.10937,7.355468 l 7.76367,-1.166015 c 0,-4.16064 -1.2188,-6.189454 -3.6543,-6.189453 z m -49.507811,0.09961 c -0.71035,0 -1.219131,0.101686 -1.675781,0.253906 v 16.439453 c 0.35517,0.15221 0.863828,0.253906 1.523438,0.253906 3.4503,0 4.871093,-2.840514 4.871093,-8.421874 0,-5.733571 -1.21772,-8.525391 -4.71875,-8.525391 z M 166.6875,78.09375 h 3 v 14 h -3 z m 0,21 h 3 v 14 h -3 z"
|
||||
transform="translate(257.78125,548.75)"
|
||||
id="rect3888"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,12 +0,0 @@
|
||||
Welcome to pretix's documentation!
|
||||
==================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
admin/index
|
||||
development/index
|
||||
plugins/index
|
||||
|
||||