mirror of
https://github.com/pretix/pretix.git
synced 2026-06-26 03:46:14 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ebd5d83ca | |||
| a8997f8971 | |||
| eb068f524c | |||
| f615595547 | |||
| 8bd78eefcf | |||
| 848f7fa0e5 | |||
| 3442a543c8 | |||
| f88c24863d | |||
| 79c5160b57 | |||
| e8492cad3c | |||
| 7ea5a2b59e | |||
| 4c373518d0 | |||
| 1521c0cfcd | |||
| 3432e62e4f | |||
| 736fa38ca7 | |||
| d14dc4c5ff | |||
| 5db1a5b8af | |||
| 86a51afe9e | |||
| ea9c85a1b4 | |||
| 226ff9b044 | |||
| d8991d8138 | |||
| 83642ec9f3 | |||
| 9f0ce28ce4 | |||
| 28722fecbd | |||
| 10a5d4ac68 | |||
| ba36f6d2ce | |||
| 1e301da26c | |||
| d0307b9936 | |||
| c083ce904a | |||
| 694b915d89 | |||
| ea928ea7d4 | |||
| 36d49fbd77 | |||
| f0cb451c34 | |||
| 2c7fcd0599 | |||
| 034722fa39 | |||
| 5a6870fce1 |
+1
-2
@@ -10,8 +10,7 @@ tests:
|
||||
- cd src
|
||||
- python manage.py check
|
||||
- make all compress
|
||||
- playwright install
|
||||
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test -n 3 tests --maxfail=100
|
||||
- PRETIX_CONFIG_FILE=tests/ci_sqlite.cfg py.test -n 3 tests --ignore=tests/e2e --maxfail=100
|
||||
except:
|
||||
- '/^v.*$/'
|
||||
pypi:
|
||||
|
||||
@@ -81,7 +81,7 @@ is a python method that emulates a behavior similar to ``reverse``:
|
||||
|
||||
If you need to communicate the URL externally, you can use a different method to ensure that it is always an absolute URL:
|
||||
|
||||
.. autofunction:: pretix.multidomain.urlreverse.build_absolute_uri
|
||||
.. autofunction:: pretix.multidomain.urlreverse.eventreverse_absolute
|
||||
|
||||
In addition, there is a template tag that works similar to ``url`` but takes an event or organizer object
|
||||
as its first argument and can be used like this::
|
||||
|
||||
Generated
+109
-91
@@ -370,14 +370,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
|
||||
"integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz",
|
||||
"integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tybys/wasm-util": "^0.10.1"
|
||||
"@tybys/wasm-util": "^0.10.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -427,9 +427,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxc-project/types": {
|
||||
"version": "0.129.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.129.0.tgz",
|
||||
"integrity": "sha512-3oz8m3FGdr2nDXVqmFUw7jolKliC4MoyXYIG2c7gpjBnzUWQpUGIYcXYKxTdTi+N2jusvt610ckTMkxdwHkYEg==",
|
||||
"version": "0.133.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz",
|
||||
"integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
@@ -758,9 +758,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0.tgz",
|
||||
"integrity": "sha512-TWMZnRLMe63C2Lhyicviu7ZHaU4kxa6PS3rofvc9GmcvptzNN11BcfQ4Sl7MwTOsisQoa2keB/EBdNCAnUo8vA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -775,9 +775,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-arm64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0.tgz",
|
||||
"integrity": "sha512-6XcD+8k0gPVItNagEw78/qqcBDwKcwDYS8V2hRmVsfUSIrd8cWe/CBvRDI5toqFyPfj+FJr6t8U6Xj2P2prEew==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -792,9 +792,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-darwin-x64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0.tgz",
|
||||
"integrity": "sha512-iN/tWVXRQDWvmZlKdceP1Dwug9GDpEymhb9p4xnEe6zvCg5lFmzVljl+1qR1NVx3yfGpr2Na+CuLmv5IU8uzfQ==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz",
|
||||
"integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -809,9 +809,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-freebsd-x64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0.tgz",
|
||||
"integrity": "sha512-jjQMDvvwSOuhOwMszD/klSOjyWMM3zI64hWTj9KT5x4MxRbZAf+7vLQ6qouRhtsLVFHr3f0ILaJAfgENPiQdAQ==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz",
|
||||
"integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -826,9 +826,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0.tgz",
|
||||
"integrity": "sha512-d//Dtg2x6/m3mbV64yUGNnDGNZaDGRpDLLNGerHQUVObuNaIQaaDp25yUiqGXtHEXX+NP2d0wAlmKgpYgIAJ2A==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz",
|
||||
"integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -843,13 +843,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-gnu": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0.tgz",
|
||||
"integrity": "sha512-n7Ofp0mx+aB2cC+Sdy5YtMnXtY9lchnHbY+3Yt0uq9JsWQExf4f5Whu0tK0R8Jdc9S6RchTHjIFY7uc92puOVQ==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -860,13 +863,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-arm64-musl": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0.tgz",
|
||||
"integrity": "sha512-EIVjy2cgd7uuMMo94FVkBp7F6DhcZAUwNURkSG3RwUmvAXR6s0ISxM81U+IydcZByPG0pZIHsf1b6kTxoFDgJA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz",
|
||||
"integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -877,13 +883,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0.tgz",
|
||||
"integrity": "sha512-JEwwOPcwTLAcpDQlqSmjEmfs63xJnSiUNIGvLcDLUHCWK4XowpS/7c7tUsUH6uT/ct6bMUTdXKfI8967FYj6mg==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -894,13 +903,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-s390x-gnu": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0.tgz",
|
||||
"integrity": "sha512-0wjCFhLrihtAubnT9iA0N++0pSV0z5Hg7tNGdNJ4RFaINceHadoF+kiFGyY1qSSNVIAZtLotG8Ju1bgDPkjnFA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -911,13 +923,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-gnu": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0.tgz",
|
||||
"integrity": "sha512-Dfn7iak9BcMMePxcoJfpSbWqnEyrp/dRF63/8qW/eHBdOZov6x5aShLLEYGYdIeSJ6vMLK/XCVB+lGIxm41bQA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz",
|
||||
"integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"glibc"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -928,13 +943,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-linux-x64-musl": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0.tgz",
|
||||
"integrity": "sha512-5/utzzDmD/pD/bmuaUcbTf/sZYy0aztwIVlfpoW1fTjCZ0BaPOMVWGZL1zvgxyi7ZIVYWlxKONHmSbHuiOh8Jw==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz",
|
||||
"integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"libc": [
|
||||
"musl"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
@@ -945,9 +963,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-openharmony-arm64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0.tgz",
|
||||
"integrity": "sha512-ouJs8VcUomfLfpbUECqFMRqdV4x6aeAK3MA4m6vTrJJjKyWTV5KnxZx7Jd9G+GlDaQQxubcba00x16OyJ1meig==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz",
|
||||
"integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -962,9 +980,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-wasm32-wasi": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0.tgz",
|
||||
"integrity": "sha512-E+oHKGiDA+lsKMmFtffDDw91EryDT7uJocrIuCHqhm6bCTM6xFK+3gaCkYOHfPwQr0cCNarSM2xaELoQDz9jJg==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz",
|
||||
"integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==",
|
||||
"cpu": [
|
||||
"wasm32"
|
||||
],
|
||||
@@ -981,9 +999,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-arm64-msvc": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0.tgz",
|
||||
"integrity": "sha512-yYK02n8Rngo+gbm1y6G0+7jk1sJ/2Wt7K0me0Y7k/ErBpyf+LJ2gFpqWVTcRV1rUepBlQRmpgWkTQCiiwrK0Ow==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz",
|
||||
"integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -998,9 +1016,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-win32-x64-msvc": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0.tgz",
|
||||
"integrity": "sha512-14bpChMahXRRXiTwahSl+zzHPW6qQTXtkMuJBFlbo+pqSAews2d4BdCSHfrJ/MBsCZtpmTafsY+1QhBzitcmdg==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz",
|
||||
"integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -3158,9 +3176,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.11",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
||||
"version": "3.3.12",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
|
||||
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -3334,9 +3352,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.14",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
|
||||
"integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
|
||||
"version": "8.5.15",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
||||
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -3353,7 +3371,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"nanoid": "^3.3.12",
|
||||
"picocolors": "^1.1.1",
|
||||
"source-map-js": "^1.2.1"
|
||||
},
|
||||
@@ -3610,14 +3628,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0.tgz",
|
||||
"integrity": "sha512-yD986aXDESFGS95spT1LAv0jssywP4npMEjmMHyN2/5+eE8qQJUype2AaKkRiLgBgyD0LFlubwAht7VmY8rGoA==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz",
|
||||
"integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@oxc-project/types": "=0.129.0",
|
||||
"@rolldown/pluginutils": "1.0.0"
|
||||
"@oxc-project/types": "=0.133.0",
|
||||
"@rolldown/pluginutils": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"rolldown": "bin/cli.mjs"
|
||||
@@ -3626,27 +3644,27 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rolldown/binding-android-arm64": "1.0.0",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.0",
|
||||
"@rolldown/binding-darwin-x64": "1.0.0",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.0",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.0",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.0",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.0",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.0",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.0",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.0",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.0",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.0",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.0",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.0"
|
||||
"@rolldown/binding-android-arm64": "1.0.3",
|
||||
"@rolldown/binding-darwin-arm64": "1.0.3",
|
||||
"@rolldown/binding-darwin-x64": "1.0.3",
|
||||
"@rolldown/binding-freebsd-x64": "1.0.3",
|
||||
"@rolldown/binding-linux-arm-gnueabihf": "1.0.3",
|
||||
"@rolldown/binding-linux-arm64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-arm64-musl": "1.0.3",
|
||||
"@rolldown/binding-linux-ppc64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-s390x-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-x64-gnu": "1.0.3",
|
||||
"@rolldown/binding-linux-x64-musl": "1.0.3",
|
||||
"@rolldown/binding-openharmony-arm64": "1.0.3",
|
||||
"@rolldown/binding-wasm32-wasi": "1.0.3",
|
||||
"@rolldown/binding-win32-arm64-msvc": "1.0.3",
|
||||
"@rolldown/binding-win32-x64-msvc": "1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown/node_modules/@rolldown/pluginutils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0.tgz",
|
||||
"integrity": "sha512-aKs/3GSWyV0mrhNmt/96/Z3yczC3yvrzYATCiCXQebBsGyYzjNdUphRVLeJQ67ySKVXRfMxt2lm12pmXvbPFQQ==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
|
||||
"integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -4325,9 +4343,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.16",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
|
||||
"integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
|
||||
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4465,17 +4483,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "8.0.12",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.12.tgz",
|
||||
"integrity": "sha512-w2dDofOWv2QB09ZITZBsvKTVAlYvPR4IAmrY/v0ir9KvLs0xybR7i48wxhM1/oyBWO34wPns+bPGw5ZrZqDpZg==",
|
||||
"version": "8.0.16",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
|
||||
"integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"lightningcss": "^1.32.0",
|
||||
"picomatch": "^4.0.4",
|
||||
"postcss": "^8.5.14",
|
||||
"rolldown": "1.0.0",
|
||||
"tinyglobby": "^0.2.16"
|
||||
"postcss": "^8.5.15",
|
||||
"rolldown": "1.0.3",
|
||||
"tinyglobby": "^0.2.17"
|
||||
},
|
||||
"bin": {
|
||||
"vite": "bin/vite.js"
|
||||
|
||||
+5
-5
@@ -33,8 +33,8 @@ dependencies = [
|
||||
"bleach==6.4.*",
|
||||
"celery==5.6.*",
|
||||
"chardet==5.2.*",
|
||||
"cryptography>=48.0.0",
|
||||
"css-inline==0.20.*",
|
||||
"cryptography>=49.0.0",
|
||||
"css-inline==0.21.*",
|
||||
"defusedcsv>=3.0.0",
|
||||
"dnspython==2.*",
|
||||
"Django[argon2]==5.2.*",
|
||||
@@ -93,7 +93,7 @@ dependencies = [
|
||||
"redis==7.4.*",
|
||||
"reportlab==4.5.*",
|
||||
"requests==2.32.*",
|
||||
"sentry-sdk==2.62.*",
|
||||
"sentry-sdk==2.63.*",
|
||||
"sepaxml==2.7.*",
|
||||
"stripe==7.9.*",
|
||||
"text-unidecode==1.*",
|
||||
@@ -101,7 +101,7 @@ dependencies = [
|
||||
"tqdm==4.*",
|
||||
"ua-parser==1.0.*",
|
||||
"vobject==0.9.*",
|
||||
"webauthn==2.7.*",
|
||||
"webauthn==2.8.*",
|
||||
"zeep==4.3.*"
|
||||
]
|
||||
|
||||
@@ -125,7 +125,7 @@ dev = [
|
||||
"pytest-sugar",
|
||||
"pytest-xdist==3.8.*",
|
||||
"pytest-playwright",
|
||||
"pytest==9.0.*",
|
||||
"pytest==9.1.*",
|
||||
"playwright",
|
||||
"responses",
|
||||
]
|
||||
|
||||
@@ -73,7 +73,7 @@ from pretix.base.settings import (
|
||||
LazyI18nStringList, validate_event_settings,
|
||||
)
|
||||
from pretix.base.signals import api_event_settings_fields
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -173,7 +173,7 @@ class EventSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer):
|
||||
)
|
||||
|
||||
def get_event_url(self, event):
|
||||
return build_absolute_uri(event, 'presale:event.index')
|
||||
return eventreverse_absolute(event, 'presale:event.index')
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
|
||||
@@ -76,7 +76,7 @@ from pretix.base.settings import (
|
||||
)
|
||||
from pretix.base.signals import register_ticket_outputs
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -757,7 +757,7 @@ class PaymentURLField(serializers.URLField):
|
||||
def to_representation(self, instance: OrderPayment):
|
||||
if instance.state != OrderPayment.PAYMENT_STATE_CREATED:
|
||||
return None
|
||||
return build_absolute_uri(instance.order.event, 'presale:event.order.pay', kwargs={
|
||||
return eventreverse_absolute(instance.order.event, 'presale:event.order.pay', kwargs={
|
||||
'order': instance.order.code,
|
||||
'secret': instance.order.secret,
|
||||
'payment': instance.pk,
|
||||
@@ -806,7 +806,7 @@ class OrderRefundSerializer(I18nAwareModelSerializer):
|
||||
|
||||
class OrderURLField(serializers.URLField):
|
||||
def to_representation(self, instance: Order):
|
||||
return build_absolute_uri(instance.event, 'presale:event.order', kwargs={
|
||||
return eventreverse_absolute(instance.event, 'presale:event.order', kwargs={
|
||||
'order': instance.code,
|
||||
'secret': instance.secret,
|
||||
})
|
||||
|
||||
@@ -58,8 +58,8 @@ from pretix.helpers.permission_migration import (
|
||||
OLD_TO_NEW_EVENT_COMPAT, OLD_TO_NEW_EVENT_MIGRATION,
|
||||
OLD_TO_NEW_ORGANIZER_COMPAT, OLD_TO_NEW_ORGANIZER_MIGRATION,
|
||||
)
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -71,7 +71,7 @@ class OrganizerSerializer(I18nAwareModelSerializer):
|
||||
slug = serializers.CharField(read_only=True)
|
||||
|
||||
def get_organizer_url(self, organizer):
|
||||
return build_absolute_uri(organizer, 'presale:organizer.index')
|
||||
return eventreverse_absolute(organizer, 'presale:organizer.index')
|
||||
|
||||
class Meta:
|
||||
model = Organizer
|
||||
@@ -499,7 +499,7 @@ class TeamInviteSerializer(serializers.ModelSerializer):
|
||||
'user': self,
|
||||
'organizer': self.context['organizer'].name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'url': mainreverse_absolute('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
|
||||
@@ -872,6 +872,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force,
|
||||
'media_policy': e.media_policy,
|
||||
'media_type': e.media_type,
|
||||
'list': MiniCheckinListSerializer(list_by_event[op.order.event_id]).data,
|
||||
'reason': e.code,
|
||||
'reason_explanation': e.msg,
|
||||
}, status=400)
|
||||
except CheckInError as e:
|
||||
|
||||
@@ -36,7 +36,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from requests import RequestException
|
||||
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -313,7 +313,7 @@ def _get_or_create_server_keypair(organizer):
|
||||
|
||||
def generate_id_token(customer, client, auth_time, nonce, scope, expires: datetime, scope_claims=False, with_code=None, with_access_token=None):
|
||||
payload = {
|
||||
'iss': build_absolute_uri(client.organizer, 'presale:organizer.index').rstrip('/'),
|
||||
'iss': eventreverse_absolute(client.organizer, 'presale:organizer.index').rstrip('/'),
|
||||
'aud': client.client_id,
|
||||
'exp': int(expires.timestamp()),
|
||||
'iat': int(time.time()),
|
||||
|
||||
@@ -28,7 +28,7 @@ from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
|
||||
from pretix.base.models import Checkin, InvoiceAddress, Order, Question
|
||||
from pretix.base.settings import PERSON_NAME_SCHEMES
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
|
||||
def get_answer(op, question_identifier=None):
|
||||
@@ -545,7 +545,7 @@ def get_data_fields(event, for_model=None):
|
||||
_("Order link"),
|
||||
Question.TYPE_STRING,
|
||||
None,
|
||||
lambda order: build_absolute_uri(
|
||||
lambda order: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order', kwargs={
|
||||
'order': order.code,
|
||||
@@ -560,7 +560,7 @@ def get_data_fields(event, for_model=None):
|
||||
_("Ticket link"),
|
||||
Question.TYPE_STRING,
|
||||
None,
|
||||
lambda op: build_absolute_uri(
|
||||
lambda op: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position', kwargs={
|
||||
'order': op.order.code,
|
||||
|
||||
@@ -68,7 +68,7 @@ from ...control.forms.filter import get_all_payment_providers
|
||||
from ...helpers import GroupConcat
|
||||
from ...helpers.iter import chunked_iterable
|
||||
from ...helpers.safe_openpyxl import remove_invalid_excel_chars
|
||||
from ...multidomain.urlreverse import build_absolute_uri
|
||||
from ...multidomain.urlreverse import eventreverse_absolute
|
||||
from ..exporter import (
|
||||
ListExporter, MultiSheetListExporter, OrganizerLevelExportMixin,
|
||||
)
|
||||
@@ -429,7 +429,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
]))
|
||||
|
||||
row.append(
|
||||
build_absolute_uri(order.event, 'presale:event.order', kwargs={
|
||||
eventreverse_absolute(order.event, 'presale:event.order', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
})
|
||||
@@ -855,7 +855,7 @@ class OrderListExporter(MultiSheetListExporter):
|
||||
]))
|
||||
|
||||
row.append(
|
||||
build_absolute_uri(order.event, 'presale:event.order.position', kwargs={
|
||||
eventreverse_absolute(order.event, 'presale:event.order.position', kwargs={
|
||||
'order': order.code,
|
||||
'secret': op.web_secret,
|
||||
'position': op.positionid
|
||||
|
||||
@@ -22,9 +22,7 @@
|
||||
import datetime
|
||||
import logging
|
||||
import math
|
||||
import re
|
||||
import textwrap
|
||||
import unicodedata
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
@@ -58,8 +56,8 @@ from pretix.base.services.currencies import SOURCE_NAMES
|
||||
from pretix.base.signals import register_invoice_renderers
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.helpers.reportlab import (
|
||||
FontFallbackParagraph, ThumbnailingImageReader, register_ttf_font_if_new,
|
||||
reshaper,
|
||||
FontFallbackParagraph, PlainTextParagraph, ThumbnailingImageReader,
|
||||
normalize_text, register_ttf_font_if_new, reshaper,
|
||||
)
|
||||
from pretix.presale.style import get_fonts
|
||||
|
||||
@@ -259,18 +257,8 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
|
||||
register_ttf_font_if_new(family + ' B I', finders.find(styles['bolditalic']['truetype']))
|
||||
|
||||
def _normalize(self, text):
|
||||
# reportlab does not support unicode combination characters
|
||||
# It's important we do this before we use ArabicReshaper
|
||||
text = unicodedata.normalize("NFKC", text)
|
||||
|
||||
# reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper
|
||||
# to resolve all ligatures and python-bidi to switch RTL texts.
|
||||
try:
|
||||
text = "<br />".join(get_display(reshaper.reshape(l)) for l in re.split("<br ?/>", text))
|
||||
except:
|
||||
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
|
||||
|
||||
return text
|
||||
# alias kept for plugin compatibility
|
||||
return normalize_text(text)
|
||||
|
||||
def _upper(self, val):
|
||||
# We uppercase labels, but not in every language
|
||||
@@ -351,10 +339,15 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
|
||||
return 'invoice.pdf', 'application/pdf', buffer.read()
|
||||
|
||||
def _clean_text(self, text, tags=None):
|
||||
return self._normalize(bleach.clean(
|
||||
text,
|
||||
tags=set(tags) if tags else set()
|
||||
).strip().replace('<br>', '<br />').replace('\n', '<br />\n'))
|
||||
# For backwards compatibility with customer content, we need to support tags like <br> and <b> in a few text
|
||||
# fields. Therefore, we can't use PlainTextParagraph for these, but run bleach instead to limit the allowed
|
||||
# tags.
|
||||
return self._normalize(
|
||||
bleach.clean(
|
||||
text,
|
||||
tags=set(tags) if tags else set()
|
||||
).strip().replace('<br>', '<br />').replace('\n', '<br />\n')
|
||||
)
|
||||
|
||||
|
||||
class PaidMarker(Flowable):
|
||||
@@ -405,8 +398,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
invoice_to_top = 52 * mm
|
||||
|
||||
def _draw_invoice_to(self, canvas):
|
||||
p = FontFallbackParagraph(self._clean_text(self.invoice.address_invoice_to),
|
||||
style=self.stylesheet['Normal'])
|
||||
p = PlainTextParagraph(self.invoice.address_invoice_to, style=self.stylesheet['Normal'])
|
||||
p.wrapOn(canvas, self.invoice_to_width, self.invoice_to_height)
|
||||
p_size = p.wrap(self.invoice_to_width, self.invoice_to_height)
|
||||
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - p_size[1] - self.invoice_to_top)
|
||||
@@ -417,8 +409,8 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
invoice_from_top = 17 * mm
|
||||
|
||||
def _draw_invoice_from(self, canvas):
|
||||
p = FontFallbackParagraph(
|
||||
self._clean_text(self.invoice.full_invoice_from),
|
||||
p = PlainTextParagraph(
|
||||
self.invoice.full_invoice_from,
|
||||
style=self.stylesheet['InvoiceFrom']
|
||||
)
|
||||
p.wrapOn(canvas, self.invoice_from_width, self.invoice_from_height)
|
||||
@@ -548,13 +540,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
def _draw_event(self, canvas):
|
||||
def shorten(txt):
|
||||
txt = str(txt)
|
||||
txt = bleach.clean(txt, tags=set()).strip()
|
||||
p = FontFallbackParagraph(self._normalize(txt.strip().replace('\n', '<br />\n')), style=self.stylesheet['Normal'])
|
||||
p = PlainTextParagraph(txt, style=self.stylesheet['Normal'])
|
||||
p_size = p.wrap(self.event_width, self.event_height)
|
||||
|
||||
while p_size[1] > 2 * self.stylesheet['Normal'].leading:
|
||||
txt = ' '.join(txt.replace('…', '').split()[:-1]) + '…'
|
||||
p = FontFallbackParagraph(self._normalize(txt.strip().replace('\n', '<br />\n')), style=self.stylesheet['Normal'])
|
||||
p = PlainTextParagraph(txt, style=self.stylesheet['Normal'])
|
||||
p_size = p.wrap(self.event_width, self.event_height)
|
||||
return txt
|
||||
|
||||
@@ -572,7 +563,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
else:
|
||||
p_str = shorten(self.invoice.event.name)
|
||||
|
||||
p = FontFallbackParagraph(self._normalize(p_str.strip().replace('\n', '<br />\n')), style=self.stylesheet['Normal'])
|
||||
p = PlainTextParagraph(p_str, style=self.stylesheet['Normal'])
|
||||
p.wrapOn(canvas, self.event_width, self.event_height)
|
||||
p_size = p.wrap(self.event_width, self.event_height)
|
||||
p.drawOn(canvas, self.event_left, self.pagesize[1] - self.event_top - p_size[1])
|
||||
@@ -645,39 +636,37 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
|
||||
type_info_text = self.invoice.transmission_type_instance.pdf_info_text()
|
||||
if type_info_text:
|
||||
story.append(FontFallbackParagraph(
|
||||
story.append(PlainTextParagraph(
|
||||
type_info_text,
|
||||
self.stylesheet['WarningBlock']
|
||||
))
|
||||
|
||||
if self.invoice.custom_field:
|
||||
story.append(FontFallbackParagraph(
|
||||
story.append(PlainTextParagraph(
|
||||
'{}: {}'.format(
|
||||
self._clean_text(str(self.invoice.event.settings.invoice_address_custom_field)),
|
||||
self._clean_text(self.invoice.custom_field),
|
||||
str(self.invoice.event.settings.invoice_address_custom_field),
|
||||
self.invoice.custom_field,
|
||||
),
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
if self.invoice.internal_reference:
|
||||
story.append(FontFallbackParagraph(
|
||||
self._normalize(pgettext('invoice', 'Customer reference: {reference}').format(
|
||||
reference=self._clean_text(self.invoice.internal_reference),
|
||||
)),
|
||||
story.append(PlainTextParagraph(
|
||||
pgettext('invoice', 'Customer reference: {reference}').format(
|
||||
reference=self.invoice.internal_reference,
|
||||
),
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
if self.invoice.invoice_to_vat_id:
|
||||
story.append(FontFallbackParagraph(
|
||||
self._normalize(pgettext('invoice', 'Customer VAT ID')) + ': ' +
|
||||
self._clean_text(self.invoice.invoice_to_vat_id),
|
||||
story.append(PlainTextParagraph(
|
||||
pgettext('invoice', 'Customer VAT ID') + ': ' + self.invoice.invoice_to_vat_id,
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
if self.invoice.invoice_to_beneficiary:
|
||||
story.append(FontFallbackParagraph(
|
||||
self._normalize(pgettext('invoice', 'Beneficiary')) + ':<br />' +
|
||||
self._clean_text(self.invoice.invoice_to_beneficiary),
|
||||
story.append(PlainTextParagraph(
|
||||
pgettext('invoice', 'Beneficiary') + ':\n' + self.invoice.invoice_to_beneficiary,
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
@@ -707,11 +696,11 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
|
||||
story = [
|
||||
NextPageTemplate('FirstPage'),
|
||||
FontFallbackParagraph(
|
||||
self._normalize(
|
||||
PlainTextParagraph(
|
||||
(
|
||||
pgettext('invoice', 'Tax Invoice') if str(self.invoice.invoice_from_country) == 'AU'
|
||||
else pgettext('invoice', 'Invoice')
|
||||
) if not self.invoice.is_cancellation else self._normalize(pgettext('invoice', 'Cancellation')),
|
||||
) if not self.invoice.is_cancellation else pgettext('invoice', 'Cancellation'),
|
||||
self.stylesheet['Heading1']
|
||||
),
|
||||
Spacer(1, 5 * mm),
|
||||
@@ -733,17 +722,17 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
]
|
||||
if has_taxes:
|
||||
tdata = [(
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Description')), self.stylesheet['Bold']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Qty')), self.stylesheet['BoldRightNoSplit']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax rate')), self.stylesheet['BoldRightNoSplit']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Net')), self.stylesheet['BoldRightNoSplit']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Gross')), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Description'), self.stylesheet['Bold']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Qty'), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Tax rate'), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Net'), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Gross'), self.stylesheet['BoldRightNoSplit']),
|
||||
)]
|
||||
else:
|
||||
tdata = [(
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Description')), self.stylesheet['Bold']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Qty')), self.stylesheet['BoldRightNoSplit']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Amount')), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Description'), self.stylesheet['Bold']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Qty'), self.stylesheet['BoldRightNoSplit']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Amount'), self.stylesheet['BoldRightNoSplit']),
|
||||
)]
|
||||
|
||||
def _group_key(line):
|
||||
@@ -780,8 +769,8 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
max_height = self.stylesheet['Normal'].leading * 5
|
||||
p_style = self.stylesheet['Normal']
|
||||
for __ in range(1000):
|
||||
p = FontFallbackParagraph(
|
||||
self._clean_text(curr_description, tags=['br']),
|
||||
p = PlainTextParagraph(
|
||||
curr_description,
|
||||
p_style
|
||||
)
|
||||
h = p.wrap(max_width, doc.height)[1]
|
||||
@@ -862,7 +851,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
# Group together at the end of the invoice
|
||||
request_show_service_date = period_line
|
||||
elif period_line:
|
||||
description_p_list.append(FontFallbackParagraph(
|
||||
description_p_list.append(PlainTextParagraph(
|
||||
period_line,
|
||||
self.stylesheet['Fineprint']
|
||||
))
|
||||
@@ -874,7 +863,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
net_price=money_filter(net_value, self.invoice.event.currency),
|
||||
gross_price=money_filter(gross_value, self.invoice.event.currency),
|
||||
)
|
||||
description_p_list.append(FontFallbackParagraph(
|
||||
description_p_list.append(PlainTextParagraph(
|
||||
single_price_line,
|
||||
self.stylesheet['Fineprint']
|
||||
))
|
||||
@@ -883,11 +872,11 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
description_p_list.pop(0),
|
||||
str(len(lines)),
|
||||
localize(tax_rate) + " %",
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(net_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
|
||||
self.stylesheet['NormalRight']
|
||||
),
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(gross_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
|
||||
self.stylesheet['NormalRight']
|
||||
),
|
||||
@@ -904,14 +893,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
single_price_line = pgettext('invoice', 'Single price: {price}').format(
|
||||
price=money_filter(gross_value, self.invoice.event.currency),
|
||||
)
|
||||
description_p_list.append(FontFallbackParagraph(
|
||||
description_p_list.append(PlainTextParagraph(
|
||||
single_price_line,
|
||||
self.stylesheet['Fineprint']
|
||||
))
|
||||
tdata.append((
|
||||
description_p_list.pop(0),
|
||||
str(len(lines)),
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(gross_value * len(lines), self.invoice.event.currency).replace('\xa0', ' '),
|
||||
self.stylesheet['NormalRight']
|
||||
),
|
||||
@@ -944,12 +933,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
|
||||
if has_taxes:
|
||||
tdata.append([
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '', '', '',
|
||||
PlainTextParagraph(pgettext('invoice', 'Invoice total'), self.stylesheet['Bold']), '', '', '',
|
||||
money_filter(total, self.invoice.event.currency)
|
||||
])
|
||||
else:
|
||||
tdata.append([
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Invoice total')), self.stylesheet['Bold']), '',
|
||||
PlainTextParagraph(pgettext('invoice', 'Invoice total'), self.stylesheet['Bold']), '',
|
||||
money_filter(total, self.invoice.event.currency)
|
||||
])
|
||||
|
||||
@@ -958,12 +947,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
pending_sum = self.invoice.order.pending_sum
|
||||
if pending_sum != total:
|
||||
tdata.append(
|
||||
[FontFallbackParagraph(self._normalize(pgettext('invoice', 'Received payments')), self.stylesheet['Normal'])] +
|
||||
[PlainTextParagraph(pgettext('invoice', 'Received payments'), self.stylesheet['Normal'])] +
|
||||
(['', '', ''] if has_taxes else ['']) +
|
||||
[money_filter(pending_sum - total, self.invoice.event.currency)]
|
||||
)
|
||||
tdata.append(
|
||||
[FontFallbackParagraph(self._normalize(pgettext('invoice', 'Outstanding payments')), self.stylesheet['Bold'])] +
|
||||
[PlainTextParagraph(pgettext('invoice', 'Outstanding payments'), self.stylesheet['Bold'])] +
|
||||
(['', '', ''] if has_taxes else ['']) +
|
||||
[money_filter(pending_sum, self.invoice.event.currency)]
|
||||
)
|
||||
@@ -980,12 +969,12 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
s=Sum('amount')
|
||||
)['s'] or Decimal('0.00')
|
||||
tdata.append(
|
||||
[FontFallbackParagraph(self._normalize(pgettext('invoice', 'Paid by gift card')), self.stylesheet['Normal'])] +
|
||||
[PlainTextParagraph(pgettext('invoice', 'Paid by gift card'), self.stylesheet['Normal'])] +
|
||||
(['', '', ''] if has_taxes else ['']) +
|
||||
[money_filter(giftcard_sum, self.invoice.event.currency)]
|
||||
)
|
||||
tdata.append(
|
||||
[FontFallbackParagraph(self._normalize(pgettext('invoice', 'Remaining amount')), self.stylesheet['Bold'])] +
|
||||
[PlainTextParagraph(pgettext('invoice', 'Remaining amount'), self.stylesheet['Bold'])] +
|
||||
(['', '', ''] if has_taxes else ['']) +
|
||||
[money_filter(total - giftcard_sum, self.invoice.event.currency)]
|
||||
)
|
||||
@@ -1008,14 +997,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
story.append(Spacer(1, 10 * mm))
|
||||
|
||||
if request_show_service_date:
|
||||
story.append(FontFallbackParagraph(
|
||||
self._normalize(pgettext('invoice', 'Invoice period: {daterange}').format(daterange=request_show_service_date)),
|
||||
story.append(PlainTextParagraph(
|
||||
pgettext('invoice', 'Invoice period: {daterange}').format(daterange=request_show_service_date),
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
if self.invoice.payment_provider_text:
|
||||
story.append(FontFallbackParagraph(
|
||||
self._normalize(self.invoice.payment_provider_text),
|
||||
self._clean_text(self.invoice.payment_provider_text, tags=['br', 'b']),
|
||||
self.stylesheet['Normal']
|
||||
))
|
||||
|
||||
@@ -1039,10 +1028,10 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
('FONTNAME', (0, 0), (-1, -1), self.font_regular),
|
||||
]
|
||||
thead = [
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax rate')), self.stylesheet['Fineprint']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Net value')), self.stylesheet['FineprintRight']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Gross value')), self.stylesheet['FineprintRight']),
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Tax')), self.stylesheet['FineprintRight']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Tax rate'), self.stylesheet['Fineprint']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Net value'), self.stylesheet['FineprintRight']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Gross value'), self.stylesheet['FineprintRight']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Tax'), self.stylesheet['FineprintRight']),
|
||||
''
|
||||
]
|
||||
tdata = [thead]
|
||||
@@ -1053,7 +1042,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
continue
|
||||
tax = taxvalue_map[idx]
|
||||
tdata.append([
|
||||
FontFallbackParagraph(self._normalize(localize(rate) + " % " + name), self.stylesheet['Fineprint']),
|
||||
PlainTextParagraph(localize(rate) + " % " + name, self.stylesheet['Fineprint']),
|
||||
money_filter(gross - tax, self.invoice.event.currency),
|
||||
money_filter(gross, self.invoice.event.currency),
|
||||
money_filter(tax, self.invoice.event.currency),
|
||||
@@ -1072,7 +1061,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
table.setStyle(TableStyle(tstyledata))
|
||||
story.append(Spacer(5 * mm, 5 * mm))
|
||||
story.append(KeepTogether([
|
||||
FontFallbackParagraph(self._normalize(pgettext('invoice', 'Included taxes')), self.stylesheet['FineprintHeading']),
|
||||
PlainTextParagraph(pgettext('invoice', 'Included taxes'), self.stylesheet['FineprintHeading']),
|
||||
table
|
||||
]))
|
||||
|
||||
@@ -1089,7 +1078,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
net = gross - tax
|
||||
|
||||
tdata.append([
|
||||
FontFallbackParagraph(self._normalize(localize(rate) + " % " + name), self.stylesheet['Fineprint']),
|
||||
PlainTextParagraph(localize(rate) + " % " + name, self.stylesheet['Fineprint']),
|
||||
fmt(net), fmt(gross), fmt(tax), ''
|
||||
])
|
||||
|
||||
@@ -1098,13 +1087,13 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
|
||||
story.append(KeepTogether([
|
||||
Spacer(1, height=2 * mm),
|
||||
FontFallbackParagraph(
|
||||
self._normalize(pgettext(
|
||||
PlainTextParagraph(
|
||||
pgettext(
|
||||
'invoice', 'Using the conversion rate of 1:{rate} as published by the {authority} on '
|
||||
'{date}, this corresponds to:'
|
||||
).format(rate=localize(self.invoice.foreign_currency_rate),
|
||||
authority=SOURCE_NAMES.get(self.invoice.foreign_currency_source, "?"),
|
||||
date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT"))),
|
||||
date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT")),
|
||||
self.stylesheet['Fineprint']
|
||||
),
|
||||
Spacer(1, height=3 * mm),
|
||||
@@ -1113,14 +1102,14 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
elif self.invoice.foreign_currency_display and self.invoice.foreign_currency_rate:
|
||||
foreign_total = round_decimal(total * self.invoice.foreign_currency_rate)
|
||||
story.append(Spacer(1, 5 * mm))
|
||||
story.append(FontFallbackParagraph(self._normalize(
|
||||
story.append(PlainTextParagraph(
|
||||
pgettext(
|
||||
'invoice', 'Using the conversion rate of 1:{rate} as published by the {authority} on '
|
||||
'{date}, the invoice total corresponds to {total}.'
|
||||
).format(rate=localize(self.invoice.foreign_currency_rate),
|
||||
date=date_format(self.invoice.foreign_currency_rate_date, "SHORT_DATE_FORMAT"),
|
||||
authority=SOURCE_NAMES.get(self.invoice.foreign_currency_source, "?"),
|
||||
total=fmt(foreign_total))),
|
||||
total=fmt(foreign_total)),
|
||||
self.stylesheet['Fineprint']
|
||||
))
|
||||
|
||||
@@ -1162,11 +1151,8 @@ class Modern1Renderer(ClassicInvoiceRenderer):
|
||||
def _draw_invoice_from(self, canvas):
|
||||
if not self.invoice.address_invoice_from:
|
||||
return
|
||||
c = [
|
||||
self._clean_text(l)
|
||||
for l in self.invoice.address_invoice_from.strip().split('\n')
|
||||
]
|
||||
p = FontFallbackParagraph(self._normalize(' · '.join(c)), style=self.stylesheet['Sender'])
|
||||
c = self.invoice.address_invoice_from.strip().split('\n')
|
||||
p = PlainTextParagraph(' · '.join(c), style=self.stylesheet['Sender'])
|
||||
p.wrapOn(canvas, self.invoice_to_width, 15.7 * mm)
|
||||
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - self.invoice_to_top + 2 * mm)
|
||||
super()._draw_invoice_from(canvas)
|
||||
@@ -1225,8 +1211,8 @@ class Modern1Renderer(ClassicInvoiceRenderer):
|
||||
_draw(pgettext('invoice', 'Order code'), self.invoice.order.full_code, value_size, self.left_margin, 45 * mm, **kwargs)
|
||||
]
|
||||
|
||||
p = FontFallbackParagraph(
|
||||
self._normalize(date_format(self.invoice.date, "DATE_FORMAT")),
|
||||
p = PlainTextParagraph(
|
||||
date_format(self.invoice.date, "DATE_FORMAT"),
|
||||
style=ParagraphStyle(name=f'Normal{value_size}', fontName=self.font_regular, fontSize=value_size, leading=value_size * 1.2)
|
||||
)
|
||||
w = stringWidth(p.text, p.frags[0].fontName, p.frags[0].fontSize)
|
||||
@@ -1283,7 +1269,7 @@ class Modern1SimplifiedRenderer(Modern1Renderer):
|
||||
i = []
|
||||
|
||||
if not self.invoice.event.has_subevents and self.invoice.event.settings.show_dates_on_frontpage:
|
||||
i.append(FontFallbackParagraph(
|
||||
i.append(PlainTextParagraph(
|
||||
pgettext('invoice', 'Event date: {date_range}').format(
|
||||
date_range=self.invoice.event.get_date_range_display(),
|
||||
),
|
||||
|
||||
@@ -282,10 +282,12 @@ def metric_values():
|
||||
|
||||
# Throwaway metrics
|
||||
exact_tables = [
|
||||
Order, OrderPosition, Invoice, Event, Organizer
|
||||
Order, Invoice, Event, Organizer
|
||||
]
|
||||
for m in apps.get_models(): # Count all models
|
||||
if any(issubclass(m, p) for p in exact_tables):
|
||||
if issubclass(m, OrderPosition):
|
||||
metrics['pretix_model_instances']['{model="%s"}' % m._meta] = m.all.count()
|
||||
elif any(issubclass(m, p) for p in exact_tables):
|
||||
metrics['pretix_model_instances']['{model="%s"}' % m._meta] = m.objects.count()
|
||||
else:
|
||||
metrics['pretix_model_instances']['{model="%s"}' % m._meta] = estimate_count_fast(m)
|
||||
|
||||
@@ -74,6 +74,7 @@ class LocaleMiddleware(MiddlewareMixin):
|
||||
|
||||
def process_request(self, request: HttpRequest):
|
||||
language = get_language_from_request(request)
|
||||
region = None
|
||||
# Normally, this middleware runs *before* the event is set. However, on event frontend pages it
|
||||
# might be run a second time by pretix.presale.EventMiddleware and in this case the event is already
|
||||
# set and can be taken into account for the decision.
|
||||
@@ -94,15 +95,16 @@ class LocaleMiddleware(MiddlewareMixin):
|
||||
if '-' not in language and settings_holder.settings.region:
|
||||
language += '-' + settings_holder.settings.region
|
||||
if settings_holder.settings.region:
|
||||
set_region(settings_holder.settings.region)
|
||||
region = settings_holder.settings.region
|
||||
else:
|
||||
gs = global_settings_object(request)
|
||||
if '-' not in language and gs.settings.region:
|
||||
language += '-' + gs.settings.region
|
||||
if gs.settings.region:
|
||||
set_region(gs.settings.region)
|
||||
region = gs.settings.region
|
||||
|
||||
translation.activate(language)
|
||||
set_region(region)
|
||||
request.LANGUAGE_CODE = get_language_without_region()
|
||||
|
||||
tzname = None
|
||||
@@ -368,8 +370,16 @@ class RejectInvalidInputMiddleware(MiddlewareMixin):
|
||||
if "\x00" in request.META['QUERY_STRING'] or "%00" in request.META['QUERY_STRING']:
|
||||
raise BadRequest("Invalid characters in input.")
|
||||
if request.method in ('POST', 'PUT', 'PATCH') and request.content_type == "application/x-www-form-urlencoded":
|
||||
if any("\x00" in value for key, value_list in request.POST.lists() for value in value_list):
|
||||
raise BadRequest("Invalid characters in input.")
|
||||
try:
|
||||
post_data = request.POST.lists()
|
||||
except BadRequest:
|
||||
# Reading request.POST wasn't possible, probably an invalid charset. Django will crash once we actually
|
||||
# use request.POST, but if we don't, let's not crash it (required for some weird payment provider
|
||||
# webhooks, e.g. computop).
|
||||
pass
|
||||
else:
|
||||
if any("\x00" in value for key, value_list in post_data for value in value_list):
|
||||
raise BadRequest("Invalid characters in input.")
|
||||
|
||||
|
||||
class CustomCommonMiddleware(CommonMiddleware):
|
||||
|
||||
@@ -57,7 +57,7 @@ from django_otp.models import Device
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
from ...helpers.countries import FastCountryField
|
||||
from ...helpers.u2f import pub_key_from_der, websafe_decode
|
||||
@@ -378,7 +378,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
|
||||
{
|
||||
'user': self,
|
||||
'messages': msg,
|
||||
'url': build_absolute_uri('control:user.settings'),
|
||||
'url': mainreverse_absolute('control:user.settings'),
|
||||
'instance': settings.PRETIX_INSTANCE_NAME,
|
||||
},
|
||||
event=None,
|
||||
@@ -466,7 +466,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
|
||||
{
|
||||
'instance': settings.PRETIX_INSTANCE_NAME,
|
||||
'user': self,
|
||||
'url': (build_absolute_uri('control:auth.forgot.recover')
|
||||
'url': (mainreverse_absolute('control:auth.forgot.recover')
|
||||
+ '?id=%d&token=%s' % (self.id, default_token_generator.make_token(self)))
|
||||
},
|
||||
None, locale=self.locale, user=self
|
||||
|
||||
@@ -167,7 +167,7 @@ class Customer(LoggedModel):
|
||||
|
||||
def send_security_notice(self, message, email=None):
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
try:
|
||||
with language(self.locale):
|
||||
@@ -178,7 +178,7 @@ class Customer(LoggedModel):
|
||||
{
|
||||
**self.get_email_context(),
|
||||
'message': str(message),
|
||||
'url': build_absolute_uri(self.organizer, 'presale:organizer.customer.index')
|
||||
'url': eventreverse_absolute(self.organizer, 'presale:organizer.customer.index')
|
||||
},
|
||||
customer=self,
|
||||
organizer=self.organizer,
|
||||
@@ -299,12 +299,12 @@ class Customer(LoggedModel):
|
||||
|
||||
def send_activation_mail(self):
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.forms.customer import TokenGenerator
|
||||
|
||||
ctx = self.get_email_context()
|
||||
token = TokenGenerator().make_token(self)
|
||||
ctx['url'] = build_absolute_uri(
|
||||
ctx['url'] = eventreverse_absolute(
|
||||
self.organizer,
|
||||
'presale:organizer.customer.activate'
|
||||
) + '?id=' + self.identifier + '&token=' + token
|
||||
|
||||
@@ -724,7 +724,7 @@ class Event(EventMixin, LoggedModel):
|
||||
|
||||
@property
|
||||
def social_image(self):
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
img = None
|
||||
logo_file = self.settings.get('logo_image', as_type=str, default='')[7:]
|
||||
@@ -742,7 +742,7 @@ class Event(EventMixin, LoggedModel):
|
||||
logger.exception(f'Failed to create thumbnail of {logo_file}')
|
||||
img = default_storage.url(logo_file)
|
||||
if img:
|
||||
return urljoin(build_absolute_uri(self, 'presale:event.index'), img)
|
||||
return urljoin(eventreverse_absolute(self, 'presale:event.index'), img)
|
||||
|
||||
def _seats(self, ignore_voucher=None):
|
||||
from .seating import Seat
|
||||
@@ -883,6 +883,8 @@ class Event(EventMixin, LoggedModel):
|
||||
ItemProgramTime, ItemVariationMetaValue, Question, Quota,
|
||||
)
|
||||
|
||||
is_cross_organizer = other.organizer_id != self.organizer_id
|
||||
|
||||
# Note: avoid self.set_active_plugins(), it causes trouble e.g. for the badges plugin.
|
||||
# Plugins can create data in installed() hook based on existing data of the event.
|
||||
# Calling set_active_plugins() results in defaults being created while actually data
|
||||
@@ -911,6 +913,15 @@ class Event(EventMixin, LoggedModel):
|
||||
for emv in EventMetaValue.objects.filter(event=other):
|
||||
emv.pk = None
|
||||
emv.event = self
|
||||
if is_cross_organizer:
|
||||
try:
|
||||
emv.property = self.organizer.meta_properties.get(name=emv.property.name)
|
||||
except EventMetaProperty.DoesNotExist:
|
||||
meta_prop = emv.property
|
||||
meta_prop.pk = None
|
||||
meta_prop.organizer = self.organizer
|
||||
meta_prop.save(force_insert=True)
|
||||
emv.property = meta_prop
|
||||
emv.save(force_insert=True)
|
||||
|
||||
for fl in EventFooterLink.objects.filter(event=other):
|
||||
@@ -964,13 +975,13 @@ class Event(EventMixin, LoggedModel):
|
||||
if i.tax_rule_id:
|
||||
i.tax_rule = tax_map[i.tax_rule_id]
|
||||
|
||||
if i.grant_membership_type and other.organizer_id != self.organizer_id:
|
||||
if i.grant_membership_type and is_cross_organizer:
|
||||
i.grant_membership_type = None
|
||||
|
||||
i.save() # no force_insert since i.picture.save could have already inserted
|
||||
i.log_action('pretix.object.cloned')
|
||||
|
||||
if require_membership_types and other.organizer_id == self.organizer_id:
|
||||
if require_membership_types and not is_cross_organizer:
|
||||
i.require_membership_types.set(require_membership_types)
|
||||
|
||||
if not i.all_sales_channels:
|
||||
@@ -985,7 +996,7 @@ class Event(EventMixin, LoggedModel):
|
||||
v._prefetched_objects_cache = {}
|
||||
v.save(force_insert=True)
|
||||
|
||||
if require_membership_types and other.organizer_id == self.organizer_id:
|
||||
if require_membership_types and not is_cross_organizer:
|
||||
v.require_membership_types.set(require_membership_types)
|
||||
if not v.all_sales_channels:
|
||||
v.limit_sales_channels.set(self.organizer.sales_channels.filter(identifier__in=[s.identifier for s in limit_sales_channels]))
|
||||
@@ -1869,6 +1880,8 @@ class EventMetaValue(LoggedModel):
|
||||
self.event.cache.clear()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.event and self.event.organizer != self.property.organizer:
|
||||
raise ValidationError(_("Property and event must belong to the same organizer."))
|
||||
super().save(*args, **kwargs)
|
||||
if self.event:
|
||||
self.event.cache.clear()
|
||||
|
||||
@@ -354,38 +354,60 @@ class Order(LockModel, LoggedModel):
|
||||
def _transaction_key_reset(self):
|
||||
self.__initial_status_paid_or_pending = self.status in (Order.STATUS_PENDING, Order.STATUS_PAID) and not self.require_approval
|
||||
|
||||
def gracefully_delete(self, user=None, auth=None):
|
||||
from . import GiftCard, GiftCardTransaction, Membership, Voucher
|
||||
|
||||
if not self.testmode:
|
||||
raise TypeError("Only test mode orders can be deleted.")
|
||||
self.log_action(
|
||||
'pretix.event.order.deleted', user=user, auth=auth,
|
||||
data={
|
||||
'code': self.code,
|
||||
}
|
||||
@classmethod
|
||||
def gracefully_delete_bulk(cls, event, orders, user=None, auth=None):
|
||||
# Expects to be called in a transaction
|
||||
from . import (
|
||||
GiftCard, GiftCardTransaction, LogEntry, Membership, Voucher,
|
||||
)
|
||||
|
||||
order_gracefully_delete.send(self.event, order=self)
|
||||
if not transaction.get_connection().in_atomic_block:
|
||||
raise Exception('gracefully_delete_bulk should only be called in atomic transaction!')
|
||||
|
||||
if self.status != Order.STATUS_CANCELED:
|
||||
for position in self.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
logs_create = []
|
||||
for o in orders:
|
||||
if not o.testmode:
|
||||
raise TypeError("Only test mode orders can be deleted.")
|
||||
order_gracefully_delete.send(event, order=o)
|
||||
logs_create.append(o.log_action(
|
||||
'pretix.event.order.deleted', user=user, auth=auth,
|
||||
data={
|
||||
'code': o.code,
|
||||
},
|
||||
save=False,
|
||||
))
|
||||
LogEntry.bulk_create_and_postprocess(logs_create)
|
||||
|
||||
GiftCardTransaction.objects.filter(payment__in=self.payments.all()).update(payment=None)
|
||||
GiftCardTransaction.objects.filter(refund__in=self.refunds.all()).update(refund=None)
|
||||
GiftCardTransaction.objects.filter(order=self).update(order=None)
|
||||
GiftCard.objects.filter(issued_in__in=self.positions.all()).update(issued_in=None)
|
||||
Membership.objects.filter(granted_in__order=self, testmode=True).update(granted_in=None)
|
||||
OrderPosition.all.filter(order=self, addon_to__isnull=False).delete()
|
||||
OrderPosition.all.filter(order=self).delete()
|
||||
OrderFee.all.filter(order=self).delete()
|
||||
Transaction.objects.filter(order=self).delete()
|
||||
self.refunds.all().delete()
|
||||
self.payments.all().delete()
|
||||
self.event.cache.delete('complain_testmode_orders')
|
||||
self.delete()
|
||||
voucher_ids = OrderPosition.objects.filter(
|
||||
order__in=orders,
|
||||
voucher__isnull=False
|
||||
).exclude(order__status=Order.STATUS_CANCELED).values_list("voucher_id", flat=True)
|
||||
voucher_usages = Counter(voucher_ids)
|
||||
for v_id, usage_count in voucher_usages.items():
|
||||
Voucher.objects.filter(pk=v_id).update(redeemed=Greatest(0, F('redeemed') - usage_count))
|
||||
|
||||
GiftCardTransaction.objects.filter(payment__order__in=orders).update(payment=None)
|
||||
GiftCardTransaction.objects.filter(refund__order__in=orders).update(refund=None)
|
||||
GiftCardTransaction.objects.filter(order__in=orders).update(order=None)
|
||||
GiftCard.objects.filter(issued_in__order__in=orders).update(issued_in=None)
|
||||
Membership.objects.filter(granted_in__order__in=orders, testmode=True).update(granted_in=None)
|
||||
OrderPosition.all.filter(order__in=orders, addon_to__isnull=False).delete()
|
||||
OrderPosition.all.filter(order__in=orders).delete()
|
||||
OrderFee.all.filter(order__in=orders).delete()
|
||||
Transaction.objects.filter(order__in=orders).delete()
|
||||
OrderRefund.objects.filter(order__in=orders).delete()
|
||||
OrderPayment.objects.filter(order__in=orders).delete()
|
||||
if isinstance(orders, models.QuerySet):
|
||||
orders.delete()
|
||||
else:
|
||||
Order.objects.filter(pk__in=[o.pk for o in orders]).delete()
|
||||
event.cache.delete('complain_testmode_orders')
|
||||
|
||||
def gracefully_delete(self, user=None, auth=None):
|
||||
if not self.testmode:
|
||||
raise TypeError("Only test mode orders can be deleted.")
|
||||
|
||||
Order.gracefully_delete_bulk(self.event, Order.objects.filter(pk=self.pk), user, auth)
|
||||
|
||||
def email_confirm_secret(self):
|
||||
return self.tagged_secret("email_confirm", 9)
|
||||
|
||||
@@ -118,7 +118,10 @@ class SeatingPlan(LoggedModel):
|
||||
for zi, z in enumerate(self.layout_data['zones']):
|
||||
zpos = (z['position']['x'], z['position']['y'])
|
||||
for ri, r in enumerate(z['rows']):
|
||||
rpos = (zpos[0] + r['position']['x'], zpos[1] + r['position']['y'])
|
||||
rpos = (
|
||||
zpos[0] + r.get('position', {}).get('x', 0),
|
||||
zpos[1] + r.get('position', {}).get('y', 0),
|
||||
)
|
||||
row_label = None
|
||||
if r.get('row_label'):
|
||||
row_label = r['row_label'].replace("%s", r.get('row_number', str(ri)))
|
||||
@@ -147,8 +150,8 @@ class SeatingPlan(LoggedModel):
|
||||
zone=z['name'],
|
||||
category=s['category'],
|
||||
sorting_rank=rank,
|
||||
x=rpos[0] + s['position']['x'],
|
||||
y=rpos[1] + s['position']['y'],
|
||||
x=rpos[0] + s.get('position', {}).get('x', 0),
|
||||
y=rpos[1] + s.get('position', {}).get('y', 0),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from pretix.base.models import Event, LogEntry
|
||||
from pretix.base.signals import register_notification_types
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_ALL_TYPES = None
|
||||
@@ -170,7 +170,7 @@ class ParametrizedOrderNotificationType(NotificationType):
|
||||
def build_notification(self, logentry: LogEntry):
|
||||
order = logentry.content_object
|
||||
|
||||
order_url = build_absolute_uri(
|
||||
order_url = mainreverse_absolute(
|
||||
'control:event.order',
|
||||
kwargs={
|
||||
'organizer': logentry.event.organizer.slug,
|
||||
|
||||
@@ -71,7 +71,7 @@ from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
from pretix.helpers.format import format_map
|
||||
from pretix.helpers.money import DecimalTextInput
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.views import get_cart
|
||||
from pretix.presale.views.cart import cart_session, get_or_create_cart_id
|
||||
|
||||
@@ -379,7 +379,7 @@ class BasePaymentProvider:
|
||||
|
||||
if not self.settings.get('_hidden_seed'):
|
||||
self.settings.set('_hidden_seed', get_random_string(64))
|
||||
hidden_url = build_absolute_uri(self.event, 'presale:event.payment.unlock', kwargs={
|
||||
hidden_url = eventreverse_absolute(self.event, 'presale:event.payment.unlock', kwargs={
|
||||
'hash': hashlib.sha256((self.settings._hidden_seed + self.event.slug).encode()).hexdigest(),
|
||||
})
|
||||
|
||||
|
||||
@@ -372,6 +372,11 @@ DEFAULT_VARIABLES = OrderedDict((
|
||||
"editor_sample": _("Atlantis"),
|
||||
"evaluate": lambda op, order, ev: str(getattr(order.invoice_address.country, 'name', '')) if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("invoice_custom_field", {
|
||||
"label": _("Invoice custom recipient field"),
|
||||
"editor_sample": _("Custom recipient field"),
|
||||
"evaluate": lambda op, order, ev: order.invoice_address.custom_field if getattr(order, 'invoice_address', None) else ''
|
||||
}),
|
||||
("addons", {
|
||||
"label": _("List of Add-Ons"),
|
||||
"editor_sample": _("Add-on 1\n2x Add-on 2"),
|
||||
@@ -1062,7 +1067,7 @@ class Renderer:
|
||||
except:
|
||||
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
|
||||
|
||||
p = Paragraph(text, style=style)
|
||||
p = Paragraph(text, style=style) # not using AutoEscapeParagraph is safe as we escape above
|
||||
return p, ad, lineheight
|
||||
|
||||
def _draw_textcontainer(self, canvas: Canvas, op: OrderPosition, order: Order, o: dict):
|
||||
|
||||
@@ -51,7 +51,7 @@ from pretix.base.signals import (
|
||||
)
|
||||
from pretix.celery_app import app
|
||||
from pretix.helpers import OF_SELF, repeatable_reads_transaction
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -455,7 +455,7 @@ def scheduled_organizer_export(self, organizer: Organizer, schedule: int) -> Non
|
||||
schedule,
|
||||
organizer,
|
||||
exporter,
|
||||
build_absolute_uri(
|
||||
mainreverse_absolute(
|
||||
'control:organizer.export',
|
||||
kwargs={
|
||||
'organizer': organizer.slug,
|
||||
@@ -481,7 +481,7 @@ def scheduled_event_export(self, event: Event, schedule: int) -> None:
|
||||
schedule,
|
||||
event,
|
||||
exporter,
|
||||
build_absolute_uri(
|
||||
mainreverse_absolute(
|
||||
'control:event.orders.export',
|
||||
kwargs={
|
||||
'event': event.slug,
|
||||
|
||||
@@ -85,7 +85,7 @@ from pretix.helpers.format import (
|
||||
FormattedString, PlainHtmlAlternativeString, SafeFormatter, format_map,
|
||||
)
|
||||
from pretix.helpers.hierarkey import clean_filename
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.ical import get_private_icals
|
||||
|
||||
logger = logging.getLogger('pretix.base.mail')
|
||||
@@ -997,7 +997,7 @@ def _wrap_plain_body(content_plain, signature, event, order, position, no_order_
|
||||
body_plain += _(
|
||||
"You can view your order details at the following URL:\n{orderurl}."
|
||||
).replace("\n", "\r\n").format(
|
||||
orderurl=build_absolute_uri(
|
||||
orderurl=eventreverse_absolute(
|
||||
order.event, 'presale:event.order.position', kwargs={
|
||||
'order': order.code,
|
||||
'secret': position.web_secret,
|
||||
@@ -1013,7 +1013,7 @@ def _wrap_plain_body(content_plain, signature, event, order, position, no_order_
|
||||
body_plain += _(
|
||||
"You can view your order details at the following URL:\n{orderurl}."
|
||||
).replace("\n", "\r\n").format(
|
||||
event=event.name, orderurl=build_absolute_uri(
|
||||
event=event.name, orderurl=eventreverse_absolute(
|
||||
order.event, 'presale:event.order.open', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
|
||||
@@ -37,7 +37,7 @@ from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask
|
||||
from pretix.base.signals import notification
|
||||
from pretix.celery_app import app
|
||||
from pretix.helpers.celery import get_task_priority
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
|
||||
@app.task(base=TransactionAwareTask, acks_late=True, max_retries=9, default_retry_delay=900)
|
||||
@@ -136,10 +136,10 @@ def send_notification_mail(notification: Notification, user: User):
|
||||
'site_url': settings.SITE_URL,
|
||||
'color': settings.PRETIX_PRIMARY_COLOR,
|
||||
'notification': notification,
|
||||
'settings_url': build_absolute_uri(
|
||||
'settings_url': mainreverse_absolute(
|
||||
'control:user.settings.notifications',
|
||||
),
|
||||
'disable_url': build_absolute_uri(
|
||||
'disable_url': mainreverse_absolute(
|
||||
'control:user.settings.notifications.off',
|
||||
kwargs={
|
||||
'token': user.notifications_token,
|
||||
|
||||
@@ -327,7 +327,7 @@ def get_best_name(position_or_address, parts=False):
|
||||
|
||||
@receiver(register_text_placeholders, dispatch_uid="pretixbase_register_text_placeholders")
|
||||
def base_placeholders(sender, **kwargs):
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
def _event_sample(event):
|
||||
if event.has_subevents:
|
||||
@@ -388,14 +388,14 @@ def base_placeholders(sender, **kwargs):
|
||||
lambda event: LazyDate(now() + timedelta(days=15))
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url', ['order', 'event'], lambda order, event: build_absolute_uri(
|
||||
'url', ['order', 'event'], lambda order, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.open', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
'hash': order.email_confirm_secret()
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.open', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -406,7 +406,7 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
SimpleButtonPlaceholder(
|
||||
'url_button', ['order', 'event'],
|
||||
url_func=lambda order, event: build_absolute_uri(
|
||||
url_func=lambda order, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.open', kwargs={
|
||||
'order': order.code,
|
||||
@@ -415,7 +415,7 @@ def base_placeholders(sender, **kwargs):
|
||||
}
|
||||
),
|
||||
text_func=lambda order, event: _("View order details"),
|
||||
sample_url_func=lambda event: build_absolute_uri(
|
||||
sample_url_func=lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.open', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -426,13 +426,13 @@ def base_placeholders(sender, **kwargs):
|
||||
sample_text_func=lambda event: _("View order details"),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_info_change', ['order', 'event'], lambda order, event: build_absolute_uri(
|
||||
'url_info_change', ['order', 'event'], lambda order, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.modify', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.modify', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -441,13 +441,13 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_products_change', ['order', 'event'], lambda order, event: build_absolute_uri(
|
||||
'url_products_change', ['order', 'event'], lambda order, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.change', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.change', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -456,13 +456,13 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_cancel', ['order', 'event'], lambda order, event: build_absolute_uri(
|
||||
'url_cancel', ['order', 'event'], lambda order, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.cancel', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret,
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.cancel', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -471,7 +471,7 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url', ['event', 'position'], lambda event, position: build_absolute_uri(
|
||||
'url', ['event', 'position'], lambda event, position: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position',
|
||||
kwargs={
|
||||
@@ -480,7 +480,7 @@ def base_placeholders(sender, **kwargs):
|
||||
'position': position.positionid
|
||||
}
|
||||
),
|
||||
lambda event: build_absolute_uri(
|
||||
lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -491,7 +491,7 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
SimpleButtonPlaceholder(
|
||||
'url_button', ['event', 'position'],
|
||||
url_func=lambda event, position: build_absolute_uri(
|
||||
url_func=lambda event, position: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position', kwargs={
|
||||
'order': position.order.code,
|
||||
@@ -500,7 +500,7 @@ def base_placeholders(sender, **kwargs):
|
||||
}
|
||||
),
|
||||
text_func=lambda event, position: _("View registration details"),
|
||||
sample_url_func=lambda event: build_absolute_uri(
|
||||
sample_url_func=lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -511,14 +511,14 @@ def base_placeholders(sender, **kwargs):
|
||||
sample_text_func=lambda event: _("View registration details"),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_info_change', ['position', 'event'], lambda position, event: build_absolute_uri(
|
||||
'url_info_change', ['position', 'event'], lambda position, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position.modify', kwargs={
|
||||
'order': position.order.code,
|
||||
'secret': position.web_secret,
|
||||
'position': position.positionid
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position.modify', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -528,14 +528,14 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_products_change', ['position', 'event'], lambda position, event: build_absolute_uri(
|
||||
'url_products_change', ['position', 'event'], lambda position, event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position.change', kwargs={
|
||||
'order': position.order.code,
|
||||
'secret': position.web_secret,
|
||||
'position': position.positionid
|
||||
}
|
||||
), lambda event: build_absolute_uri(
|
||||
), lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.order.position.change', kwargs={
|
||||
'order': 'F8VVL',
|
||||
@@ -581,20 +581,20 @@ def base_placeholders(sender, **kwargs):
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url_remove', ['waiting_list_voucher', 'event'],
|
||||
lambda waiting_list_voucher, event: build_absolute_uri(
|
||||
lambda waiting_list_voucher, event: eventreverse_absolute(
|
||||
event, 'presale:event.waitinglist.remove'
|
||||
) + '?voucher=' + waiting_list_voucher.code,
|
||||
lambda event: build_absolute_uri(
|
||||
lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.waitinglist.remove',
|
||||
) + '?voucher=68CYU2H6ZTP3WLK5',
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url', ['waiting_list_voucher', 'event'],
|
||||
lambda waiting_list_voucher, event: build_absolute_uri(
|
||||
lambda waiting_list_voucher, event: eventreverse_absolute(
|
||||
event, 'presale:event.redeem'
|
||||
) + '?voucher=' + waiting_list_voucher.code,
|
||||
lambda event: build_absolute_uri(
|
||||
lambda event: eventreverse_absolute(
|
||||
event,
|
||||
'presale:event.redeem',
|
||||
) + '?voucher=68CYU2H6ZTP3WLK5',
|
||||
@@ -611,7 +611,7 @@ def base_placeholders(sender, **kwargs):
|
||||
'orders', ['event', 'orders'], lambda event, orders: '\n' + '\n\n'.join(
|
||||
'* {} - {}'.format(
|
||||
order.full_code,
|
||||
build_absolute_uri(event, 'presale:event.order.open', kwargs={
|
||||
eventreverse_absolute(event, 'presale:event.order.open', kwargs={
|
||||
'event': event.slug,
|
||||
'organizer': event.organizer.slug,
|
||||
'order': order.code,
|
||||
@@ -623,7 +623,7 @@ def base_placeholders(sender, **kwargs):
|
||||
), lambda event: '\n' + '\n\n'.join(
|
||||
'* {} - {}'.format(
|
||||
'{}-{}'.format(event.slug.upper(), order['code']),
|
||||
build_absolute_uri(event, 'presale:event.order.open', kwargs={
|
||||
eventreverse_absolute(event, 'presale:event.order.open', kwargs={
|
||||
'event': event.slug,
|
||||
'organizer': event.organizer.slug,
|
||||
'order': order['code'],
|
||||
@@ -662,13 +662,13 @@ def base_placeholders(sender, **kwargs):
|
||||
# join vouchers with two spaces at end of line so markdown-parser inserts a <br>
|
||||
'voucher_url_list', ['event', 'voucher_list'],
|
||||
lambda event, voucher_list: ' \n'.join([
|
||||
build_absolute_uri(
|
||||
eventreverse_absolute(
|
||||
event, 'presale:event.redeem'
|
||||
) + '?voucher=' + c
|
||||
for c in voucher_list
|
||||
]),
|
||||
lambda event: ' \n'.join([
|
||||
build_absolute_uri(
|
||||
eventreverse_absolute(
|
||||
event, 'presale:event.redeem'
|
||||
) + '?voucher=' + c
|
||||
for c in ['68CYU2H6ZTP3WLK5', '7MB94KKPVEPSMVF2']
|
||||
@@ -676,10 +676,10 @@ def base_placeholders(sender, **kwargs):
|
||||
inline=False,
|
||||
),
|
||||
SimpleFunctionalTextPlaceholder(
|
||||
'url', ['event', 'voucher_list'], lambda event, voucher_list: build_absolute_uri(event, 'presale:event.index', kwargs={
|
||||
'url', ['event', 'voucher_list'], lambda event, voucher_list: eventreverse_absolute(event, 'presale:event.index', kwargs={
|
||||
'event': event.slug,
|
||||
'organizer': event.organizer.slug,
|
||||
}), lambda event: build_absolute_uri(event, 'presale:event.index', kwargs={
|
||||
}), lambda event: eventreverse_absolute(event, 'presale:event.index', kwargs={
|
||||
'event': event.slug,
|
||||
'organizer': event.organizer.slug,
|
||||
})
|
||||
|
||||
@@ -37,7 +37,7 @@ from pretix.base.services.mail import mail
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
from pretix.base.signals import periodic_task
|
||||
from pretix.celery_app import app
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
|
||||
@receiver(signal=periodic_task)
|
||||
@@ -121,7 +121,7 @@ def send_update_notification_email():
|
||||
)
|
||||
),
|
||||
{
|
||||
'url': build_absolute_uri('control:global.update')
|
||||
'url': mainreverse_absolute('control:global.update')
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<link rel="icon" href="{% static "pretixbase/img/favicon.ico" %}">
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/errors.js" %}"></script>
|
||||
{% block custom_header %}{% endblock %}
|
||||
{% if css_theme %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ css_theme }}" />
|
||||
@@ -20,6 +21,5 @@
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<script src="{% static "pretixbase/js/errors.js" %}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
{% load i18n %}
|
||||
{% load rich_text %}
|
||||
{% load static %}
|
||||
{% load wrap_in %}
|
||||
{% block title %}{% trans "Redirect" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-link fa-fw big-icon"></i>
|
||||
<div class="error-details">
|
||||
<h1>{% trans "Redirect" %}</h1>
|
||||
<h3>
|
||||
{% blocktrans trimmed with host="<strong>"|add:hostname|add:"</strong>"|safe %}
|
||||
{% blocktrans trimmed with host=hostname|wrap_in:'strong' %}
|
||||
The link you clicked on wants to redirect you to a destination on the website {{ host }}.
|
||||
{% endblocktrans %}
|
||||
{% blocktrans trimmed %}
|
||||
|
||||
@@ -80,7 +80,7 @@ from pretix.control.forms.widgets import Select2
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
from pretix.multidomain.models import AlternativeDomainAssignment, KnownDomain
|
||||
from pretix.multidomain.urlreverse import (
|
||||
build_absolute_uri, get_organizer_domain,
|
||||
eventreverse_absolute, get_organizer_domain,
|
||||
)
|
||||
from pretix.plugins.banktransfer.payment import BankTransfer
|
||||
from pretix.presale.style import get_fonts
|
||||
@@ -219,7 +219,7 @@ class EventWizardBasicsForm(I18nModelForm):
|
||||
self.fields['location'].widget.attrs['placeholder'] = _(
|
||||
'Sample Conference Center\nHeidelberg, Germany'
|
||||
)
|
||||
self.fields['slug'].widget.prefix = build_absolute_uri(self.organizer, 'presale:organizer.index')
|
||||
self.fields['slug'].widget.prefix = eventreverse_absolute(self.organizer, 'presale:organizer.index')
|
||||
self.fields['tax_rate']._required = True # Do not render as optional because it is conditionally required
|
||||
if self.has_subevents:
|
||||
del self.fields['presale_start']
|
||||
|
||||
@@ -1342,7 +1342,13 @@ class QuestionAnswerFilterForm(forms.Form):
|
||||
opqs = opqs.filter(canceled=False)
|
||||
if fdata.get("item", "") != "":
|
||||
i = fdata.get("item", "")
|
||||
opqs = opqs.filter(item_id__in=(i,))
|
||||
if '-' in i:
|
||||
opqs = opqs.filter(
|
||||
item_id=i.split('-')[0],
|
||||
variation_id=i.split('-')[1],
|
||||
)
|
||||
else:
|
||||
opqs = opqs.filter(item_id=i)
|
||||
|
||||
return opqs
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ from pretix.control.forms.event import (
|
||||
)
|
||||
from pretix.control.forms.widgets import Select2, Select2Multiple
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
|
||||
class OrganizerForm(I18nModelForm):
|
||||
@@ -791,7 +791,7 @@ class MailSettingsForm(SettingsForm):
|
||||
}
|
||||
|
||||
if 'url' in base_parameters:
|
||||
placeholders['url'] = build_absolute_uri(
|
||||
placeholders['url'] = eventreverse_absolute(
|
||||
self.organizer,
|
||||
'presale:organizer.customer.activate'
|
||||
) + '?token=' + get_random_string(30)
|
||||
|
||||
@@ -38,6 +38,7 @@ from pretix import __version__
|
||||
from pretix.base.models import Order, OrderPayment, Transaction
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.helpers.reportlab import PlainTextParagraph
|
||||
from pretix.plugins.reports.exporters import ReportlabExportMixin
|
||||
from pretix.settings import DATA_DIR
|
||||
|
||||
@@ -79,23 +80,23 @@ class SysReport(ReportlabExportMixin):
|
||||
style_small.fontSize = 6
|
||||
|
||||
story = [
|
||||
Paragraph("System report", headlinestyle),
|
||||
PlainTextParagraph("System report", headlinestyle),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph("Usage", subheadlinestyle),
|
||||
PlainTextParagraph("Usage", subheadlinestyle),
|
||||
Spacer(1, 5 * mm),
|
||||
self._usage_table(),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph("Installed versions", subheadlinestyle),
|
||||
PlainTextParagraph("Installed versions", subheadlinestyle),
|
||||
Spacer(1, 5 * mm),
|
||||
self._tech_table(),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph("Plugins", subheadlinestyle),
|
||||
PlainTextParagraph("Plugins", subheadlinestyle),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph(self._get_plugin_versions(), style_small),
|
||||
PlainTextParagraph(self._get_plugin_versions(), style_small),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph("Custom templates", subheadlinestyle),
|
||||
PlainTextParagraph("Custom templates", subheadlinestyle),
|
||||
Spacer(1, 5 * mm),
|
||||
Paragraph(self._get_custom_templates(), style_small),
|
||||
PlainTextParagraph(self._get_custom_templates(), style_small),
|
||||
Spacer(1, 5 * mm),
|
||||
]
|
||||
|
||||
@@ -121,13 +122,13 @@ class SysReport(ReportlabExportMixin):
|
||||
("RIGHTPADDING", (-1, 0), (-1, -1), 0),
|
||||
]
|
||||
tdata = [
|
||||
[Paragraph("Site URL:", style), Paragraph(settings.SITE_URL, style)],
|
||||
[Paragraph("pretix version:", style), Paragraph(__version__, style)],
|
||||
[Paragraph("Python version:", style), Paragraph(sys.version, style)],
|
||||
[Paragraph("Platform:", style), Paragraph(platform.platform(), style)],
|
||||
[PlainTextParagraph("Site URL:", style), Paragraph(settings.SITE_URL, style)],
|
||||
[PlainTextParagraph("pretix version:", style), Paragraph(__version__, style)],
|
||||
[PlainTextParagraph("Python version:", style), Paragraph(sys.version, style)],
|
||||
[PlainTextParagraph("Platform:", style), Paragraph(platform.platform(), style)],
|
||||
[
|
||||
Paragraph("Database engine:", style),
|
||||
Paragraph(settings.DATABASES["default"]["ENGINE"], style),
|
||||
PlainTextParagraph("Database engine:", style),
|
||||
PlainTextParagraph(settings.DATABASES["default"]["ENGINE"], style),
|
||||
],
|
||||
]
|
||||
table = Table(tdata, colWidths=colwidths, repeatRows=0)
|
||||
@@ -206,7 +207,7 @@ class SysReport(ReportlabExportMixin):
|
||||
year_last = now().year
|
||||
tdata = [
|
||||
[
|
||||
Paragraph(l, style_small_head)
|
||||
PlainTextParagraph(l, style_small_head)
|
||||
for l in (
|
||||
"Time frame",
|
||||
"Currency",
|
||||
@@ -257,19 +258,19 @@ class SysReport(ReportlabExportMixin):
|
||||
|
||||
tdata.append(
|
||||
(
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
date_format(first_day, "M Y")
|
||||
+ " – "
|
||||
+ date_format(after_day - timedelta(days=1), "M Y"),
|
||||
style_small,
|
||||
),
|
||||
Paragraph(c, style_small),
|
||||
Paragraph(str(orders_count), style_small) if i == 0 else "",
|
||||
Paragraph(money_filter(revenue_data.get("s_net") or 0, c), style_small),
|
||||
Paragraph(str(testmode_count), style_small) if i == 0 else "",
|
||||
Paragraph(str(unconfirmed_count), style_small) if i == 0 else "",
|
||||
Paragraph(str(revenue_data.get("c") or 0), style_small),
|
||||
Paragraph(money_filter(revenue_data.get("s_gross") or 0, c), style_small),
|
||||
PlainTextParagraph(c, style_small),
|
||||
PlainTextParagraph(str(orders_count), style_small) if i == 0 else "",
|
||||
PlainTextParagraph(money_filter(revenue_data.get("s_net") or 0, c), style_small),
|
||||
PlainTextParagraph(str(testmode_count), style_small) if i == 0 else "",
|
||||
PlainTextParagraph(str(unconfirmed_count), style_small) if i == 0 else "",
|
||||
PlainTextParagraph(str(revenue_data.get("c") or 0), style_small),
|
||||
PlainTextParagraph(money_filter(revenue_data.get("s_gross") or 0, c), style_small),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<script type="text/javascript" src="{% static "lightbox/js/lightbox.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "are-you-sure/jquery.are-you-sure.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/errors.js" %}"></script>
|
||||
{% endcompress %}
|
||||
{{ html_head|safe }}
|
||||
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<script type="application/json" id="editor-data">
|
||||
{{ layout|safe }}
|
||||
</script>
|
||||
{{ layout|json_script:"editor-data" }}
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div class="panel panel-default panel-pdf-editor">
|
||||
|
||||
@@ -41,7 +41,7 @@ from collections import OrderedDict, defaultdict
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
from urllib.parse import urlparse, urlsplit
|
||||
from urllib.parse import urlsplit
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import bleach
|
||||
@@ -64,7 +64,6 @@ from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import conditional_escape, format_html
|
||||
from django.utils.http import url_has_allowed_host_and_scheme
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext, gettext_lazy as _, gettext_noop
|
||||
@@ -97,7 +96,9 @@ from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.views.mailsetup import MailSettingsSetupView
|
||||
from pretix.control.views.user import RecentAuthenticationRequiredMixin
|
||||
from pretix.helpers.database import rolledback_transaction
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, get_event_domain
|
||||
from pretix.multidomain.urlreverse import (
|
||||
eventreverse_absolute, get_event_domain,
|
||||
)
|
||||
from pretix.presale.views.widget import (
|
||||
version_default as widget_version_default,
|
||||
)
|
||||
@@ -1148,8 +1149,11 @@ class EventLive(EventPermissionRequiredMixin, TemplateView):
|
||||
if request.POST.get("delete") == "yes":
|
||||
try:
|
||||
with transaction.atomic():
|
||||
for order in request.event.orders.filter(testmode=True):
|
||||
order.gracefully_delete(user=self.request.user)
|
||||
Order.gracefully_delete_bulk(
|
||||
request.event,
|
||||
request.event.orders.filter(testmode=True),
|
||||
user=self.request.user
|
||||
)
|
||||
except ProtectedError:
|
||||
messages.error(self.request, _('An order could not be deleted as some constraints (e.g. data '
|
||||
'created by plug-ins) do not allow it.'))
|
||||
@@ -1734,10 +1738,10 @@ class EventQRCode(EventPermissionRequiredMixin, View):
|
||||
permission = None
|
||||
|
||||
def get(self, request, *args, filetype, **kwargs):
|
||||
url = build_absolute_uri(request.event, 'presale:event.index')
|
||||
url = eventreverse_absolute(request.event, 'presale:event.index')
|
||||
|
||||
if "url" in request.GET:
|
||||
if url_has_allowed_host_and_scheme(request.GET["url"], allowed_hosts=[urlparse(url).netloc]):
|
||||
if request.GET["url"].startswith(url):
|
||||
url = request.GET["url"]
|
||||
else:
|
||||
raise PermissionDenied("Untrusted URL")
|
||||
|
||||
@@ -139,6 +139,7 @@ from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.format import SafeFormatter, format_map
|
||||
from pretix.helpers.hierarkey import clean_filename
|
||||
from pretix.helpers.iter import chunked_iterable
|
||||
from pretix.helpers.json import CustomJSONEncoder
|
||||
from pretix.helpers.safedownload import check_token
|
||||
from pretix.presale.signals import question_form_fields
|
||||
@@ -240,7 +241,7 @@ class BaseOrderBulkActionView(OrderSearchMixin, EventPermissionRequiredMixin, As
|
||||
raise NotImplementedError()
|
||||
|
||||
def execute_bulk(self, queryset: QuerySet, form: forms.Form):
|
||||
qs = self.allowed_for(self.allowed_for(self.get_queryset()))
|
||||
qs = self.allowed_for(self.get_queryset())
|
||||
total = qs.count()
|
||||
orders_with_successful_action = 0
|
||||
for i, o in enumerate(qs):
|
||||
@@ -394,9 +395,21 @@ class OrderDeleteBulkActionView(BaseOrderBulkActionView):
|
||||
testmode=True,
|
||||
)
|
||||
|
||||
def execute_single(self, instance, form: forms.Form):
|
||||
instance.gracefully_delete(user=self.request.user)
|
||||
return True
|
||||
def execute_bulk(self, queryset: QuerySet, form: forms.Form):
|
||||
qs = self.allowed_for(self.get_queryset())
|
||||
total = qs.count()
|
||||
all_ids = list(qs.values_list("id", flat=True))
|
||||
|
||||
orders_with_successful_action = 0
|
||||
for chunk in chunked_iterable(all_ids, 1000):
|
||||
Order.gracefully_delete_bulk(
|
||||
self.request.event,
|
||||
qs.filter(id__in=chunk),
|
||||
user=self.request.user,
|
||||
)
|
||||
orders_with_successful_action += len(chunk)
|
||||
self.async_set_progress(orders_with_successful_action / total * 100)
|
||||
return orders_with_successful_action, total
|
||||
|
||||
|
||||
class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
|
||||
@@ -139,8 +139,8 @@ from pretix.helpers import OF_SELF, GroupConcat
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
from pretix.helpers.format import SafeFormatter, format_map
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.forms.customer import TokenGenerator
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -1039,7 +1039,7 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
||||
'user': self,
|
||||
'organizer': self.request.organizer.name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'url': mainreverse_absolute('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
@@ -2851,10 +2851,12 @@ class SSOProviderUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequire
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['redirect_uri'] = build_absolute_uri(self.request.organizer, 'presale:organizer.customer.login.return',
|
||||
kwargs={
|
||||
'provider': self.object.pk
|
||||
})
|
||||
ctx['redirect_uri'] = eventreverse_absolute(
|
||||
self.request.organizer, 'presale:organizer.customer.login.return',
|
||||
kwargs={
|
||||
'provider': self.object.pk
|
||||
}
|
||||
)
|
||||
return ctx
|
||||
|
||||
def get_form_kwargs(self):
|
||||
@@ -3085,7 +3087,7 @@ class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
self.customer.log_action('pretix.customer.password.resetrequested', {}, user=self.request.user)
|
||||
ctx = self.customer.get_email_context()
|
||||
token = TokenGenerator().make_token(self.customer)
|
||||
ctx['url'] = build_absolute_uri(
|
||||
ctx['url'] = eventreverse_absolute(
|
||||
self.request.organizer,
|
||||
'presale:organizer.customer.recoverpw'
|
||||
) + '?id=' + self.customer.identifier + '&token=' + token
|
||||
|
||||
@@ -284,7 +284,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
|
||||
ctx['pdf'] = self.get_current_background()
|
||||
ctx['variables'] = self.get_variables()
|
||||
ctx['images'] = self.get_images()
|
||||
ctx['layout'] = json.dumps(self.get_current_layout())
|
||||
ctx['layout'] = self.get_current_layout()
|
||||
ctx['title'] = self.title
|
||||
ctx['locales'] = [p for p in settings.LANGUAGES if p[0] in self.request.event.settings.locales]
|
||||
ctx['maxfilesize'] = self.maxfilesize
|
||||
|
||||
@@ -77,7 +77,7 @@ from pretix.control.views import PaginationMixin
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.format import SafeFormatter, format_map
|
||||
from pretix.helpers.models import modelcopy
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
|
||||
class VoucherList(PaginationMixin, EventPermissionRequiredMixin, ListView):
|
||||
@@ -338,7 +338,7 @@ class VoucherUpdate(EventPermissionRequiredMixin, UpdateView):
|
||||
}
|
||||
if self.object.subevent_id:
|
||||
url_params['subevent'] = self.object.subevent_id
|
||||
ctx['url'] = build_absolute_uri(self.request.event, "presale:event.redeem") + "?" + urlencode(url_params)
|
||||
ctx['url'] = eventreverse_absolute(self.request.event, "presale:event.redeem") + "?" + urlencode(url_params)
|
||||
return ctx
|
||||
|
||||
|
||||
|
||||
@@ -29,3 +29,8 @@ class PretixHelpersConfig(AppConfig):
|
||||
def ready(self):
|
||||
from .monkeypatching import monkeypatch_all_at_ready
|
||||
monkeypatch_all_at_ready()
|
||||
|
||||
# Ensure reportlab does not make any calls to the internet or the local disk
|
||||
from reportlab import rl_config
|
||||
rl_config.trustedHosts = []
|
||||
rl_config.trustedSchemes = ['data']
|
||||
|
||||
@@ -27,6 +27,7 @@ from datetime import datetime
|
||||
from http import cookies
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import SuspiciousFileOperation
|
||||
from PIL import Image
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.connection import HTTPConnection, HTTPSConnection
|
||||
@@ -40,6 +41,8 @@ from urllib3.util.connection import (
|
||||
)
|
||||
from urllib3.util.timeout import _DEFAULT_TIMEOUT
|
||||
|
||||
from pretix.helpers.reportlab import ThumbnailingImageReader
|
||||
|
||||
_cgnat_net = ipaddress.ip_network('100.64.0.0/10')
|
||||
|
||||
|
||||
@@ -230,9 +233,27 @@ def monkeypatch_cookie_morsel():
|
||||
cookies.Morsel._reserved.setdefault("partitioned", "Partitioned")
|
||||
|
||||
|
||||
def monkeypatch_reportlab_imagereader():
|
||||
from reportlab.lib import utils
|
||||
old_init = utils.ImageReader.__init__
|
||||
|
||||
def new_init(self, fileName, ident=None): # noqa
|
||||
if not isinstance(fileName, Image.Image) and not hasattr(fileName, 'read') and not hasattr(fileName, 'str'):
|
||||
if not isinstance(self, ThumbnailingImageReader):
|
||||
# ThumbnailingImageReader is only used by us explicitly and not by using <img> in html, so it is safe
|
||||
raise SuspiciousFileOperation("reportlab should not be reading images from disk")
|
||||
|
||||
return types.MethodType(old_init, self)(
|
||||
fileName, ident
|
||||
)
|
||||
|
||||
utils.ImageReader.__init__ = new_init
|
||||
|
||||
|
||||
def monkeypatch_all_at_ready():
|
||||
monkeypatch_vobject_performance()
|
||||
monkeypatch_pillow_safer()
|
||||
monkeypatch_requests_timeout()
|
||||
monkeypatch_urllib3_ssrf_protection()
|
||||
monkeypatch_cookie_morsel()
|
||||
monkeypatch_reportlab_imagereader()
|
||||
|
||||
@@ -20,14 +20,19 @@
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
import re
|
||||
import unicodedata
|
||||
|
||||
from arabic_reshaper import ArabicReshaper
|
||||
from bidi import get_display
|
||||
from django.conf import settings
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.html import escape
|
||||
from PIL import Image
|
||||
from reportlab.lib.styles import ParagraphStyle
|
||||
from reportlab.lib.utils import ImageReader
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from reportlab.platypus import Paragraph
|
||||
|
||||
from pretix.presale.style import get_fonts
|
||||
@@ -70,6 +75,20 @@ reshaper = SimpleLazyObject(lambda: ArabicReshaper(configuration={
|
||||
}))
|
||||
|
||||
|
||||
def normalize_text(text: str) -> str:
|
||||
# reportlab does not support unicode combination characters
|
||||
# It's important we do this before we use ArabicReshaper
|
||||
text = unicodedata.normalize("NFKC", text)
|
||||
|
||||
# reportlab does not support RTL, ligature-heavy scripts like Arabic. Therefore, we use ArabicReshaper
|
||||
# to resolve all ligatures and python-bidi to switch RTL texts.
|
||||
try:
|
||||
text = "\n".join(get_display(reshaper.reshape(l)) for l in re.split("\n", text))
|
||||
except:
|
||||
logger.exception('Reshaping/Bidi fixes failed on string {}'.format(repr(text)))
|
||||
return text
|
||||
|
||||
|
||||
class FontFallbackParagraph(Paragraph):
|
||||
def __init__(self, text, style=None, *args, **kwargs):
|
||||
if style is None:
|
||||
@@ -87,6 +106,8 @@ class FontFallbackParagraph(Paragraph):
|
||||
if not text:
|
||||
return True
|
||||
font = pdfmetrics.getFont(font_name)
|
||||
if not isinstance(font, TTFont):
|
||||
return True
|
||||
return all(
|
||||
ord(c) in font.face.charToGlyph or not c.isprintable()
|
||||
for c in text
|
||||
@@ -102,6 +123,24 @@ class FontFallbackParagraph(Paragraph):
|
||||
return family
|
||||
|
||||
|
||||
class PlainTextParagraph(FontFallbackParagraph):
|
||||
def __init__(self, text, style=None, linebreaks=True, *args, **kwargs):
|
||||
if not isinstance(text, str):
|
||||
if hasattr(text, '__html__'):
|
||||
raise ValueError("It is contradictory to pass escaped content to PlainTextParagraph")
|
||||
text = str(text)
|
||||
|
||||
# Normalize unicode and apply reshaping
|
||||
text = normalize_text(text)
|
||||
|
||||
# Escape any HTML in the text
|
||||
text = escape(text)
|
||||
|
||||
if linebreaks:
|
||||
text = text.strip().replace("\n", "<br />\n")
|
||||
super().__init__(text, style, *args, **kwargs)
|
||||
|
||||
|
||||
def register_ttf_font_if_new(name, path):
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
|
||||
@@ -35,7 +35,7 @@ from geoip2.errors import AddressNotFoundError
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.helpers.http import get_client_ip
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -175,7 +175,7 @@ def handle_login_source(user, request):
|
||||
'source': src,
|
||||
'country': Country(str(country)).name if country else _('Unknown country'),
|
||||
'instance': settings.PRETIX_INSTANCE_NAME,
|
||||
'url': build_absolute_uri('control:user.settings')
|
||||
'url': mainreverse_absolute('control:user.settings')
|
||||
},
|
||||
event=None,
|
||||
user=user,
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from django import template
|
||||
from django.utils.html import format_html
|
||||
|
||||
register = template.Library()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@register.filter
|
||||
def wrap_in(content, tag_name):
|
||||
return format_html(f'<{tag_name}>{{}}</{tag_name}>', content)
|
||||
@@ -19,6 +19,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import warnings
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.conf import settings
|
||||
@@ -26,6 +27,15 @@ from django.urls import reverse
|
||||
|
||||
|
||||
def build_absolute_uri(urlname, args=None, kwargs=None):
|
||||
warnings.warn(
|
||||
'Usage of build_absolute_uri is confusing since there are many functions with that name. '
|
||||
'Replace this usage with ',
|
||||
DeprecationWarning
|
||||
)
|
||||
return mainreverse_absolute(urlname, args, kwargs)
|
||||
|
||||
|
||||
def mainreverse_absolute(urlname, args=None, kwargs=None):
|
||||
from pretix.multidomain import maindomain_urlconf
|
||||
|
||||
return urljoin(settings.SITE_URL, reverse(urlname, args=args, kwargs=kwargs, urlconf=maindomain_urlconf))
|
||||
|
||||
@@ -4,16 +4,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-27 15:47+0000\n"
|
||||
"PO-Revision-Date: 2026-05-22 07:03+0000\n"
|
||||
"PO-Revision-Date: 2026-06-20 17:00+0000\n"
|
||||
"Last-Translator: Nikolai <nikolai@lengefeldt.de>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/da/"
|
||||
">\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"da/>\n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 2026.5\n"
|
||||
"X-Generator: Weblate 2026.6.1\n"
|
||||
|
||||
#: htmlcov/d_daa1541d0cbf5e2b_dashboards_py.html:670
|
||||
#: pretix/control/templates/pretixcontrol/events/index.html:166
|
||||
@@ -612,16 +612,17 @@ msgstr ""
|
||||
"underordnede objekter som f.eks. varianter eller pakker."
|
||||
|
||||
#: pretix/api/webhooks.py:413
|
||||
#, fuzzy
|
||||
#| msgid "Quota handling"
|
||||
msgid "Quota changed"
|
||||
msgstr "Håndtering af kvoter"
|
||||
msgstr "Kvoten er ændret"
|
||||
|
||||
#: pretix/api/webhooks.py:414
|
||||
msgid ""
|
||||
"This includes related events like creation, deletion, opening or closing of "
|
||||
"quotas. No webhook is sent for changes to the resulting availability."
|
||||
msgstr ""
|
||||
"Dette omfatter relaterede hændelser såsom oprettelse, sletning, åbning eller "
|
||||
"lukning af kvoter. Der sendes ingen webhook ved ændringer i den deraf "
|
||||
"følgende tilgængelighed."
|
||||
|
||||
#: pretix/api/webhooks.py:419
|
||||
msgid "Shop taken live"
|
||||
@@ -3394,12 +3395,12 @@ msgstr "Indtast venligst et kortere navn."
|
||||
msgid ""
|
||||
"The field \"%(label)s\" may not contain special characters such as "
|
||||
"\"%(chars)s\"."
|
||||
msgstr ""
|
||||
msgstr "Feltet \"%(label)s\" må ikke indeholde specialtegn såsom \"%(chars)s\"."
|
||||
|
||||
#: pretix/base/forms/questions.py:305
|
||||
#, python-format
|
||||
msgid "The field \"%(label)s\" may not contain an URL (%(url)s)."
|
||||
msgstr ""
|
||||
msgstr "Feltet \"%(label)s\" må ikke indeholde en URL (%(url)s)."
|
||||
|
||||
#: pretix/base/forms/questions.py:338
|
||||
msgctxt "phonenumber"
|
||||
@@ -8290,19 +8291,14 @@ msgid "Program times"
|
||||
msgstr "Programtider"
|
||||
|
||||
#: pretix/base/pdf.py:503
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "2017-05-31 10:00 – 12:00\n"
|
||||
#| "2017-05-31 14:00 – 16:00\n"
|
||||
#| "2017-05-31 14:00 – 2017-06-01 14:00"
|
||||
msgid ""
|
||||
"2017-05-31 10:00 – 12:00, Room 1\n"
|
||||
"2017-05-31 14:00 – 16:00, Room 2\n"
|
||||
"2017-05-31 14:00 – 2017-06-01 14:00, Building A"
|
||||
msgstr ""
|
||||
"31. maj 2017 kl. 10.00 – 12.00\n"
|
||||
"31. maj 2017 kl. 14.00 – 16.00\n"
|
||||
"31. maj 2017 kl. 14.00 – 1. juni 2017 kl. 14.00"
|
||||
"31. maj 2017 kl. 10.00 – 12.00, lokale 1\n"
|
||||
"31. maj 2017 kl. 14.00 – 16.00, lokale 2\n"
|
||||
"31. maj 2017 kl. 14.00 – 1. juni 2017 kl. 14.00, bygning A"
|
||||
|
||||
#: pretix/base/pdf.py:507
|
||||
msgid "Reusable Medium ID"
|
||||
@@ -8827,13 +8823,7 @@ msgid "This voucher code is not known in our database."
|
||||
msgstr "Denne voucherkode genkendes ikke."
|
||||
|
||||
#: pretix/base/services/cart.py:165
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
#| "%(number)s matching products."
|
||||
#| msgid_plural ""
|
||||
#| "The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
#| "%(number)s matching products."
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
"%(number)s matching product."
|
||||
@@ -8841,22 +8831,14 @@ msgid_plural ""
|
||||
"The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
"%(number)s matching products."
|
||||
msgstr[0] ""
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst "
|
||||
"%(number)s passende produkter."
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst %"
|
||||
"(number)s passende produkter."
|
||||
msgstr[1] ""
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst "
|
||||
"%(number)s passende produkter."
|
||||
"Voucherkoderne \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst %"
|
||||
"(number)s passende produkter."
|
||||
|
||||
#: pretix/base/services/cart.py:170
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
#| "%(number)s matching products. We have therefore removed some positions "
|
||||
#| "from your cart that can no longer be purchased like this."
|
||||
#| msgid_plural ""
|
||||
#| "The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
#| "%(number)s matching products. We have therefore removed some positions "
|
||||
#| "from your cart that can no longer be purchased like this."
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The voucher code \"%(voucher)s\" can only be used if you select at least "
|
||||
"%(number)s matching product. We have therefore removed some positions from "
|
||||
@@ -8866,12 +8848,12 @@ msgid_plural ""
|
||||
"%(number)s matching products. We have therefore removed some positions from "
|
||||
"your cart that can no longer be purchased like this."
|
||||
msgstr[0] ""
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst "
|
||||
"%(number)s passende produkter. Vi har derfor fjernet nogle poster fra din "
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst %"
|
||||
"(number)s passende produkter. Vi har derfor fjernet nogle poster fra din "
|
||||
"indkøbskurv, som ikke længere kan blive købt på denne måde."
|
||||
msgstr[1] ""
|
||||
"Voucherkoden \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst "
|
||||
"%(number)s passende produkter. Vi har derfor fjernet nogle poster fra din "
|
||||
"Voucherkoderne \"%(voucher)s\" kan kun blive brugt, hvis du vælger mindst %"
|
||||
"(number)s passende produkter. Vi har derfor fjernet nogle poster fra din "
|
||||
"indkøbskurv, som ikke længere kan blive købt på denne måde."
|
||||
|
||||
#: pretix/base/services/cart.py:176
|
||||
@@ -14105,6 +14087,8 @@ msgid ""
|
||||
"You entered an URL, which is not allowed. Please remove %(match)s from your "
|
||||
"input."
|
||||
msgstr ""
|
||||
"Du har indtastet en URL, som ikke er tilladt. Fjern venligst %(match)s fra "
|
||||
"din indtastning."
|
||||
|
||||
#: pretix/base/views/errors.py:48
|
||||
msgid ""
|
||||
@@ -16027,14 +16011,8 @@ msgid "inactive"
|
||||
msgstr "inaktiv"
|
||||
|
||||
#: pretix/control/forms/item.py:1414
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Sample Conference Center\n"
|
||||
#| "Heidelberg, Germany"
|
||||
msgid "Sample Conference Center, Heidelberg, Germany"
|
||||
msgstr ""
|
||||
"Eksempelkonferencecenter\n"
|
||||
"Andeby, Danmark"
|
||||
msgstr "Eksempelkonferencecenter, Århus, Danmark"
|
||||
|
||||
#: pretix/control/forms/mailsetup.py:42
|
||||
msgid "Hostname"
|
||||
@@ -17819,12 +17797,11 @@ msgstr ""
|
||||
"afvist."
|
||||
|
||||
#: pretix/control/logdisplay.py:571
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"An email has been sent to notify the user that the order has been approved."
|
||||
msgstr ""
|
||||
"En e-mail er blevet sendt for at fortælle brugeren at bestillingen er "
|
||||
"modtaget."
|
||||
"Der er sendt en e-mail for at informere brugeren om, at ordren er blevet "
|
||||
"godkendt."
|
||||
|
||||
#: pretix/control/logdisplay.py:574
|
||||
msgid ""
|
||||
@@ -17835,13 +17812,12 @@ msgstr ""
|
||||
"modtaget og kræver betaling."
|
||||
|
||||
#: pretix/control/logdisplay.py:575
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"An email has been sent to notify the user that the order has been received "
|
||||
"and requires approval."
|
||||
msgstr ""
|
||||
"En e-mail er blevet sendt for at fortælle brugeren at bestillingen er "
|
||||
"modtaget og kræver betaling."
|
||||
"Der er sendt en e-mail for at informere brugeren om, at ordren er modtaget "
|
||||
"og skal godkendes."
|
||||
|
||||
#: pretix/control/logdisplay.py:578
|
||||
msgid ""
|
||||
@@ -17851,21 +17827,22 @@ msgstr ""
|
||||
"bestillingsdetaljer."
|
||||
|
||||
#: pretix/control/logdisplay.py:579
|
||||
#, fuzzy
|
||||
msgid "An email has been sent to notify the user that the payment failed."
|
||||
msgstr ""
|
||||
"En e-mail er blevet sendt for at fortælle brugeren at betaling er modtaget."
|
||||
"Der er sendt en e-mail for at informere brugeren om, at betalingen "
|
||||
"mislykkedes."
|
||||
|
||||
#: pretix/control/logdisplay.py:586
|
||||
msgid "The voucher has been created."
|
||||
msgstr "Voucheren er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:589
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The voucher has been set to expire because the recipient removed themselves "
|
||||
"from the waiting list."
|
||||
msgstr "En rabatkode er blevet sendt til en person på ventelisten."
|
||||
msgstr ""
|
||||
"Kuponen er sat til at udløbe, fordi modtageren har fjernet sig selv fra "
|
||||
"ventelisten."
|
||||
|
||||
#: pretix/control/logdisplay.py:590
|
||||
msgid "The voucher has been changed."
|
||||
@@ -17876,16 +17853,13 @@ msgid "The voucher has been deleted."
|
||||
msgstr "Voucheren er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:592
|
||||
#, fuzzy
|
||||
#| msgid "The selected voucher has been deleted."
|
||||
msgid "Cart positions including the voucher have been deleted."
|
||||
msgstr "Den valgte rabatkode er blevet slettet."
|
||||
msgstr "Indkøbskurvens varer, herunder gavekortet, er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:593
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "A voucher has been sent to a person on the waiting list."
|
||||
#, python-brace-format
|
||||
msgid "The voucher has been assigned to {email} through the waiting list."
|
||||
msgstr "En rabatkode er blevet sendt til en person på ventelisten."
|
||||
msgstr "Kuponen er blevet tildelt {email} via ventelisten."
|
||||
|
||||
#: pretix/control/logdisplay.py:602
|
||||
#, python-brace-format
|
||||
@@ -17905,9 +17879,8 @@ msgid "The category has been changed."
|
||||
msgstr "Kategorien er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:620
|
||||
#, fuzzy
|
||||
msgid "The category has been reordered."
|
||||
msgstr "Kategorien er blevet slettet."
|
||||
msgstr "Kategorien er blevet omorganiseret."
|
||||
|
||||
#: pretix/control/logdisplay.py:627
|
||||
msgid "The tax rule has been added."
|
||||
@@ -17937,14 +17910,14 @@ msgid "{user} has been invited to the team."
|
||||
msgstr "{user} er blevet inviteret med i gruppen."
|
||||
|
||||
#: pretix/control/logdisplay.py:644
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Invite for {user} has been deleted."
|
||||
msgstr "Invitationen til {user} er blevet trukket tilbage."
|
||||
msgstr "Invitationen til {user} er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:645
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Invite for {user} has been resent."
|
||||
msgstr "Invitationen til {user} er blevet trukket tilbage."
|
||||
msgstr "Invitationen til {user} er blevet sendt igen."
|
||||
|
||||
#: pretix/control/logdisplay.py:656
|
||||
#, python-brace-format
|
||||
@@ -17962,294 +17935,245 @@ msgstr "Din e-mailadresse er blevet ændret til {email}."
|
||||
|
||||
#: pretix/control/logdisplay.py:673
|
||||
msgid "Your account has been enabled."
|
||||
msgstr ""
|
||||
msgstr "Din konto er nu aktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:675
|
||||
msgid "Your account has been disabled."
|
||||
msgstr ""
|
||||
msgstr "Din konto er blevet deaktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:680 pretix/presale/views/customer.py:642
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "The email address has been changed from \"{old_email}\" to \"{new_email}"
|
||||
#| "\"."
|
||||
#, python-brace-format
|
||||
msgid "Your email address has been changed from {old_email} to {email}."
|
||||
msgstr ""
|
||||
"E-mailadressen er blevet ændret fra \"{old_email}\" til \"{new_email}\"."
|
||||
msgstr "Din e-mailadresse er blevet ændret fra {old_email} til {email}."
|
||||
|
||||
#: pretix/control/logdisplay.py:681
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Your email address {email} has been confirmed."
|
||||
msgstr "Din kurv er blevet opdateret."
|
||||
msgstr "Din e-mailadresse {email} er blevet bekræftet."
|
||||
|
||||
#: pretix/control/logdisplay.py:693
|
||||
#, python-brace-format
|
||||
msgid "You impersonated {}."
|
||||
msgstr ""
|
||||
msgstr "Du udgav dig for at være {}."
|
||||
|
||||
#: pretix/control/logdisplay.py:694
|
||||
#, python-brace-format
|
||||
msgid "You stopped impersonating {}."
|
||||
msgstr ""
|
||||
msgstr "Du er holdt op med at udgive dig for at være {}."
|
||||
|
||||
#: pretix/control/logdisplay.py:701
|
||||
msgid "This object has been created by cloning."
|
||||
msgstr "Dette objekt er blevet oprettet ved kloning"
|
||||
|
||||
#: pretix/control/logdisplay.py:702
|
||||
#, fuzzy
|
||||
msgid "The organizer has been changed."
|
||||
msgstr "Bestillingen er blevet ændret."
|
||||
msgstr "Arrangøren er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:703
|
||||
#, fuzzy
|
||||
msgid "The organizer settings have been changed."
|
||||
msgstr "Gruppeindstillingerne er blevet ændret."
|
||||
msgstr "Indstillingerne for arrangøren er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:704 pretix/control/logdisplay.py:849
|
||||
#, fuzzy
|
||||
msgid "The footer links have been changed."
|
||||
msgstr "Bestillingsdetaljerne er blevet ændret."
|
||||
msgstr "Linkene i sidefoden er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:705 pretix/control/logdisplay.py:754
|
||||
#, fuzzy
|
||||
msgid "A scheduled export has been added."
|
||||
msgstr "Kvoten er blevet tilføjet."
|
||||
msgstr "Der er tilføjet en planlagt eksport."
|
||||
|
||||
#: pretix/control/logdisplay.py:706 pretix/control/logdisplay.py:755
|
||||
#, fuzzy
|
||||
msgid "A scheduled export has been changed."
|
||||
msgstr "Produktet er blevet ændret."
|
||||
msgstr "En planlagt eksport er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:707 pretix/control/logdisplay.py:756
|
||||
#, fuzzy
|
||||
msgid "A scheduled export has been deleted."
|
||||
msgstr "Det valgte produkt er blevet slettet."
|
||||
msgstr "En planlagt eksport er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:708 pretix/control/logdisplay.py:757
|
||||
#, fuzzy
|
||||
msgid "A scheduled export has been executed."
|
||||
msgstr "Det valgte produkt er blevet slettet."
|
||||
msgstr "En planlagt eksport er blevet udført."
|
||||
|
||||
#: pretix/control/logdisplay.py:709 pretix/control/logdisplay.py:758
|
||||
#, python-brace-format
|
||||
msgid "A scheduled export has failed: {reason}."
|
||||
msgstr ""
|
||||
msgstr "En planlagt eksport er mislykket: {reason}."
|
||||
|
||||
#: pretix/control/logdisplay.py:710
|
||||
#, fuzzy
|
||||
#| msgid "The email has been queued to be sent."
|
||||
msgid "Failed emails have been scheduled to be retried."
|
||||
msgstr "Denne e-mail er sat i udsendelseskøen."
|
||||
msgstr ""
|
||||
"Der er planlagt et nyt forsøg på at sende de e-mails, der ikke kunne leveres."
|
||||
|
||||
#: pretix/control/logdisplay.py:711
|
||||
#, fuzzy
|
||||
#| msgid "The order details have been changed."
|
||||
msgid "Queued emails have been aborted."
|
||||
msgstr "Bestillingsdetaljerne er blevet ændret."
|
||||
msgstr "E-mails i køen er blevet afbrudt."
|
||||
|
||||
#: pretix/control/logdisplay.py:712
|
||||
#, fuzzy
|
||||
msgid "Gift card acceptance for another organizer has been added."
|
||||
msgstr "Den nye arrangør er blevet oprettet."
|
||||
msgstr ""
|
||||
"Der er nu tilføjet mulighed for at acceptere gavekort fra en anden arrangør."
|
||||
|
||||
#: pretix/control/logdisplay.py:713
|
||||
#, fuzzy
|
||||
msgid "Gift card acceptance for another organizer has been removed."
|
||||
msgstr "Den nye arrangør er blevet oprettet."
|
||||
msgstr ""
|
||||
"Muligheden for at modtage gavekort fra en anden arrangør er blevet fjernet."
|
||||
|
||||
#: pretix/control/logdisplay.py:714
|
||||
#, fuzzy
|
||||
msgid "A new gift card acceptor has been invited."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Der er blevet inviteret en ny modtager af gavekort."
|
||||
|
||||
#: pretix/control/logdisplay.py:715
|
||||
#, fuzzy
|
||||
msgid "A gift card acceptor has been removed."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "En gavekort-modtager er blevet fjernet."
|
||||
|
||||
#: pretix/control/logdisplay.py:716
|
||||
#, fuzzy
|
||||
msgid "A gift card issuer has been removed or declined."
|
||||
msgstr "Den valgte kategorien er blevet slettet."
|
||||
msgstr "En udsteder af gavekort er blevet fjernet eller afvist."
|
||||
|
||||
#: pretix/control/logdisplay.py:717
|
||||
#, fuzzy
|
||||
msgid "A new gift card issuer has been accepted."
|
||||
msgstr "Den valgte kategorien er blevet slettet."
|
||||
msgstr "En ny udsteder af gavekort er blevet godkendt."
|
||||
|
||||
#: pretix/control/logdisplay.py:718
|
||||
#, fuzzy
|
||||
msgid "The webhook has been created."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Webhooken er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:719
|
||||
#, fuzzy
|
||||
msgid "The webhook has been changed."
|
||||
msgstr "Kategorien er blevet ændret."
|
||||
msgstr "Webhooken er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:720
|
||||
msgid "The webhook call retry jobs have been manually expedited."
|
||||
msgstr ""
|
||||
"Opgaverne vedrørende gentagelse af webhook-kald er blevet fremskyndet "
|
||||
"manuelt."
|
||||
|
||||
#: pretix/control/logdisplay.py:721
|
||||
#, fuzzy
|
||||
msgid "The webhook call retry jobs have been dropped."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Opgaverne til gentagelse af webhook-kald er blevet annulleret."
|
||||
|
||||
#: pretix/control/logdisplay.py:722
|
||||
#, fuzzy
|
||||
msgid "The SSO provider has been created."
|
||||
msgstr "Bestilling oprettet."
|
||||
msgstr "SSO-udbyderen er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:723
|
||||
#, fuzzy
|
||||
msgid "The SSO provider has been changed."
|
||||
msgstr "Bestillingen er blevet ændret."
|
||||
msgstr "SSO-udbyderen er blevet skiftet."
|
||||
|
||||
#: pretix/control/logdisplay.py:724
|
||||
#, fuzzy
|
||||
msgid "The SSO provider has been deleted."
|
||||
msgstr "Bestillingen er blevet tilbagebetalt."
|
||||
msgstr "SSO-udbyderen er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:725
|
||||
#, fuzzy
|
||||
msgid "The SSO client has been created."
|
||||
msgstr "Arrangementsdatoen er blevet oprettet."
|
||||
msgstr "SSO-klienten er oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:726
|
||||
#, fuzzy
|
||||
msgid "The SSO client has been changed."
|
||||
msgstr "Kategorien er blevet ændret."
|
||||
msgstr "SSO-klienten er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:727
|
||||
#, fuzzy
|
||||
msgid "The SSO client has been deleted."
|
||||
msgstr "Produktet er blevet slettet."
|
||||
msgstr "SSO-klienten er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:728 pretix/control/views/organizer.py:2715
|
||||
#, fuzzy
|
||||
msgid "The membership type has been created."
|
||||
msgstr "Arrangementsdatoen er blevet oprettet."
|
||||
msgstr "Medlemskabstypen er oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:729
|
||||
#, fuzzy
|
||||
msgid "The membership type has been changed."
|
||||
msgstr "Arrangementsdatoen er blevet ændret."
|
||||
msgstr "Medlemskabstypen er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:730
|
||||
#, fuzzy
|
||||
msgid "The membership type has been deleted."
|
||||
msgstr "Arrangementsdatoen er blevet slettet."
|
||||
msgstr "Medlemskabstypen er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:731 pretix/control/views/organizer.py:3556
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "The new date has been created."
|
||||
msgid "The sales channel has been created."
|
||||
msgstr "Den nye dato er blevet oprettet."
|
||||
msgstr "Salgskanalen er oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:732
|
||||
#, fuzzy
|
||||
msgid "The sales channel has been changed."
|
||||
msgstr "Voucheren er blevet ændret."
|
||||
msgstr "Salgskanalen er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:733
|
||||
#, fuzzy
|
||||
#| msgid "The selected list has been deleted."
|
||||
msgid "The sales channel has been deleted."
|
||||
msgstr "Den valgte lister er blevet slettet."
|
||||
msgstr "Salgskanalen er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:734
|
||||
#, fuzzy
|
||||
msgid "The account has been created."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Kontoen er oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:735
|
||||
#, fuzzy
|
||||
msgid "The account has been changed."
|
||||
msgstr "Kategorien er blevet ændret."
|
||||
msgstr "Kontoen er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:736
|
||||
#, fuzzy
|
||||
msgid "A membership for this account has been added."
|
||||
msgstr "Den valgte konfiguration er blevet slettet."
|
||||
msgstr "Der er tilføjet et medlemskab til denne konto."
|
||||
|
||||
#: pretix/control/logdisplay.py:737
|
||||
#, fuzzy
|
||||
msgid "A membership of this account has been changed."
|
||||
msgstr "En svarmulighed er blevet ændret."
|
||||
msgstr "Et medlemskab på denne konto er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:738
|
||||
#, fuzzy
|
||||
msgid "A membership of this account has been deleted."
|
||||
msgstr "Den valgte konfiguration er blevet slettet."
|
||||
msgstr "Et medlemskab tilknyttet denne konto er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:739
|
||||
#, fuzzy
|
||||
msgid "The account has been disabled and anonymized."
|
||||
msgstr "Bestillingen er blevet tilbagebetalt."
|
||||
msgstr "Kontoen er blevet deaktiveret og anonymiseret."
|
||||
|
||||
#: pretix/control/logdisplay.py:740
|
||||
#, fuzzy
|
||||
msgid "A new password has been requested."
|
||||
msgstr "Adgangskoden er blevet nulstillet."
|
||||
msgstr "Der er anmodet om en ny adgangskode."
|
||||
|
||||
#: pretix/control/logdisplay.py:741
|
||||
#, fuzzy
|
||||
msgid "A new password has been set."
|
||||
msgstr "Adgangskoden er blevet nulstillet."
|
||||
msgstr "Der er blevet oprettet en ny adgangskode."
|
||||
|
||||
#: pretix/control/logdisplay.py:743
|
||||
#, fuzzy
|
||||
msgid "The reusable medium has been created."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Det genanvendelige medie er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:744
|
||||
#, fuzzy
|
||||
msgid "The reusable medium has been created automatically."
|
||||
msgstr "Arrangementsdatoen er blevet oprettet."
|
||||
msgstr "Det genanvendelige medie er blevet oprettet automatisk."
|
||||
|
||||
#: pretix/control/logdisplay.py:745
|
||||
#, fuzzy
|
||||
msgid "The reusable medium has been changed."
|
||||
msgstr "Momsreglen er blevet ændret."
|
||||
msgstr "Det genanvendelige medie er blevet udskiftet."
|
||||
|
||||
#: pretix/control/logdisplay.py:746
|
||||
#, fuzzy
|
||||
msgid "The medium has been connected to a new ticket."
|
||||
msgstr "Denne e-mail er sat i udsendelseskøen."
|
||||
msgstr "Mediet er blevet knyttet til en ny sag."
|
||||
|
||||
#: pretix/control/logdisplay.py:747
|
||||
#, fuzzy
|
||||
msgid "The medium has been connected to a new gift card."
|
||||
msgstr "Denne e-mail er sat i udsendelseskøen."
|
||||
msgstr "Mediet er blevet knyttet til et nyt gavekort."
|
||||
|
||||
#: pretix/control/logdisplay.py:749
|
||||
msgid "The event's internal comment has been updated."
|
||||
msgstr "Intern kommentar opdateret."
|
||||
|
||||
#: pretix/control/logdisplay.py:750
|
||||
#, fuzzy
|
||||
msgid "The event has been canceled."
|
||||
msgstr "Bestillingen er blevet annulleret."
|
||||
msgstr "Arrangementet er blevet aflyst."
|
||||
|
||||
#: pretix/control/logdisplay.py:751
|
||||
#, fuzzy
|
||||
msgid "An event has been deleted."
|
||||
msgstr "Arrangementsdatoen er blevet slettet."
|
||||
msgstr "En begivenhed er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:752
|
||||
msgid "A removal process for personal data has been started."
|
||||
msgstr ""
|
||||
msgstr "Der er iværksat en sletningsproces for personoplysninger."
|
||||
|
||||
#: pretix/control/logdisplay.py:753
|
||||
msgid "A removal process for personal data has been completed."
|
||||
msgstr ""
|
||||
msgstr "En sletning af personoplysninger er blevet gennemført."
|
||||
|
||||
#: pretix/control/logdisplay.py:759
|
||||
msgid "The user has been created."
|
||||
msgstr ""
|
||||
msgstr "Brugeren er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:760
|
||||
#, python-brace-format
|
||||
@@ -18257,6 +18181,8 @@ msgid ""
|
||||
"A first login using {agent_type} on {os_type} from {country} has been "
|
||||
"detected."
|
||||
msgstr ""
|
||||
"Der er registreret en første login med {agent_type} på {os_type} fra "
|
||||
"{country}."
|
||||
|
||||
#: pretix/control/logdisplay.py:762 pretix/control/views/user.py:474
|
||||
#: pretix/control/views/user.py:534 pretix/control/views/user.py:593
|
||||
@@ -18273,9 +18199,8 @@ msgid "Your two-factor emergency codes have been regenerated."
|
||||
msgstr "Dine sikkerhedskoder til tofaktorgodkendelse er blevet genoprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:765
|
||||
#, fuzzy
|
||||
msgid "A two-factor emergency code has been generated."
|
||||
msgstr "Dine sikkerhedskoder til tofaktorgodkendelse er blevet genoprettet."
|
||||
msgstr "Der er genereret en tofaktorkode til nødsituationer."
|
||||
|
||||
#: pretix/control/logdisplay.py:766
|
||||
#, python-brace-format
|
||||
@@ -18295,20 +18220,19 @@ msgstr ""
|
||||
|
||||
#: pretix/control/logdisplay.py:770
|
||||
msgid "Notifications have been enabled."
|
||||
msgstr ""
|
||||
msgstr "Notifikationer er blevet aktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:771
|
||||
msgid "Notifications have been disabled."
|
||||
msgstr ""
|
||||
msgstr "Notifikationer er blevet deaktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:772
|
||||
msgid "Your notification settings have been changed."
|
||||
msgstr ""
|
||||
msgstr "Dine notifikationsindstillinger er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:773
|
||||
#, fuzzy
|
||||
msgid "This user has been anonymized."
|
||||
msgstr "Bestillingen er blevet tilbagebetalt."
|
||||
msgstr "Denne bruger er blevet anonymiseret."
|
||||
|
||||
#: pretix/control/logdisplay.py:777
|
||||
msgid "Password reset mail sent."
|
||||
@@ -18323,20 +18247,21 @@ msgid ""
|
||||
"A repeated password reset has been denied, as the last request was less than "
|
||||
"24 hours ago."
|
||||
msgstr ""
|
||||
"En gentagen anmodning om nulstilling af adgangskode er blevet afvist, da den "
|
||||
"seneste anmodning blev fremsat for mindre end 24 timer siden."
|
||||
|
||||
#: pretix/control/logdisplay.py:781
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "The organizer \"{name}\" has been deleted."
|
||||
msgstr "Varianten \"{value}\" er blevet slettet."
|
||||
msgstr "Arrangøren \"{name}\" er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:782 pretix/control/logdisplay.py:1013
|
||||
msgid "A voucher has been sent to a person on the waiting list."
|
||||
msgstr "En rabatkode er blevet sendt til en person på ventelisten."
|
||||
|
||||
#: pretix/control/logdisplay.py:783
|
||||
#, fuzzy
|
||||
msgid "An entry has been transferred to another waiting list."
|
||||
msgstr "En bruger er føjet til gruppen."
|
||||
msgstr "En ansøgning er blevet flyttet til en anden venteliste."
|
||||
|
||||
#: pretix/control/logdisplay.py:784
|
||||
msgid "The team has been created."
|
||||
@@ -18351,19 +18276,16 @@ msgid "The team has been deleted."
|
||||
msgstr "Gruppen er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:787 pretix/control/views/organizer.py:2381
|
||||
#, fuzzy
|
||||
msgid "The gate has been created."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Porten er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:788
|
||||
#, fuzzy
|
||||
msgid "The gate has been changed."
|
||||
msgstr "Kategorien er blevet ændret."
|
||||
msgstr "Porten er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:789
|
||||
#, fuzzy
|
||||
msgid "The gate has been deleted."
|
||||
msgstr "Gruppen er blevet slettet."
|
||||
msgstr "Porten er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:790
|
||||
msgctxt "subevent"
|
||||
@@ -18371,10 +18293,9 @@ msgid "The event date has been deleted."
|
||||
msgstr "Arrangementsdatoen er blevet slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:791
|
||||
#, fuzzy
|
||||
msgctxt "subevent"
|
||||
msgid "The event date has been canceled."
|
||||
msgstr "Arrangementsdatoen er blevet ændret."
|
||||
msgstr "Begivenhedsdatoen er blevet aflyst."
|
||||
|
||||
#: pretix/control/logdisplay.py:792
|
||||
msgctxt "subevent"
|
||||
@@ -18402,58 +18323,50 @@ msgid "A quota has been removed from the event date."
|
||||
msgstr "En kvote er blevet fjernet fra arrangementsdatoen."
|
||||
|
||||
#: pretix/control/logdisplay.py:797
|
||||
#, fuzzy
|
||||
msgid "The device has been created."
|
||||
msgstr "Arrangementsdatoen er blevet oprettet."
|
||||
msgstr "Enheden er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:798
|
||||
#, fuzzy
|
||||
msgid "The device has been changed."
|
||||
msgstr "Voucheren er blevet ændret."
|
||||
msgstr "Enheden er blevet udskiftet."
|
||||
|
||||
#: pretix/control/logdisplay.py:799
|
||||
#, fuzzy
|
||||
msgid "Access of the device has been revoked."
|
||||
msgstr "Enheden er blevet fjernet."
|
||||
msgstr "Adgangen til enheden er blevet tilbagekaldt."
|
||||
|
||||
#: pretix/control/logdisplay.py:800
|
||||
#, fuzzy
|
||||
msgid "The device has been initialized."
|
||||
msgstr "Enheden er blevet fjernet."
|
||||
msgstr "Enheden er blevet initialiseret."
|
||||
|
||||
#: pretix/control/logdisplay.py:801
|
||||
#, fuzzy
|
||||
msgid "The access token of the device has been regenerated."
|
||||
msgstr "Fakturaen er blevet genereret igen."
|
||||
msgstr "Enhedens adgangstoken er blevet genereret på ny."
|
||||
|
||||
#: pretix/control/logdisplay.py:802
|
||||
msgid "The device has notified the server of an hardware or software update."
|
||||
msgstr ""
|
||||
"Enheden har meddelt serveren, at der er en hardware- eller "
|
||||
"softwareopdatering."
|
||||
|
||||
#: pretix/control/logdisplay.py:803
|
||||
#, fuzzy
|
||||
msgid "The gift card has been created."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Gavekortet er oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:804 pretix/control/views/organizer.py:1943
|
||||
#, fuzzy
|
||||
msgid "The gift card has been changed."
|
||||
msgstr "Gruppen er blevet oprettet."
|
||||
msgstr "Gavekortet er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:805
|
||||
#, fuzzy
|
||||
msgid "A manual transaction has been performed."
|
||||
msgstr "Spørgsmålet er blevet tilføjet."
|
||||
msgstr "Der er udført en manuel overførsel."
|
||||
|
||||
#: pretix/control/logdisplay.py:806
|
||||
#, fuzzy
|
||||
msgid "A payment has been performed."
|
||||
msgstr "Betalingsbetingelser er blevet ændret."
|
||||
msgstr "Der er blevet foretaget en betaling."
|
||||
|
||||
#: pretix/control/logdisplay.py:807
|
||||
#, fuzzy
|
||||
msgid "A refund has been performed. "
|
||||
msgstr "Bestilling oprettet."
|
||||
msgstr "Der er blevet foretaget en tilbagebetaling. "
|
||||
|
||||
#: pretix/control/logdisplay.py:808
|
||||
#, python-brace-format
|
||||
@@ -18466,44 +18379,34 @@ msgid "The token \"{name}\" has been revoked."
|
||||
msgstr "Token \"{name}\" slettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:810
|
||||
#, fuzzy
|
||||
#| msgid "The check-in list has been deleted."
|
||||
msgid "The check-in and print log state has been reset."
|
||||
msgstr "Tjek-ind-listen er blevet slettet."
|
||||
msgstr "Status for indtjeknings- og udskriftsloggen er blevet nulstillet."
|
||||
|
||||
#: pretix/control/logdisplay.py:817 pretix/control/logdisplay.py:876
|
||||
#, fuzzy
|
||||
#| msgid "A plugin has been enabled."
|
||||
msgid "The plugin has been enabled."
|
||||
msgstr "En plugin er blevet aktiveret."
|
||||
msgstr "Plugin'et er blevet aktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:818 pretix/control/logdisplay.py:877
|
||||
#: pretix/control/views/event.py:497 pretix/control/views/organizer.py:757
|
||||
#, fuzzy
|
||||
#| msgid "A plugin has been disabled."
|
||||
msgid "The plugin has been disabled."
|
||||
msgstr "En plugin er blevet deaktiveret."
|
||||
msgstr "Plugin'et er blevet deaktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:821 pretix/control/logdisplay.py:880
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Question {val}"
|
||||
#, python-brace-format
|
||||
msgid "Plugin {val}"
|
||||
msgstr "Spørgsmål {val}"
|
||||
msgstr "Plugin {val}"
|
||||
|
||||
#: pretix/control/logdisplay.py:836
|
||||
#, fuzzy
|
||||
msgid "A meta property has been added to this event."
|
||||
msgstr "En bruger er føjet til gruppen."
|
||||
msgstr "Der er tilføjet en metaegenskab til denne begivenhed."
|
||||
|
||||
#: pretix/control/logdisplay.py:837
|
||||
#, fuzzy
|
||||
msgid "A meta property has been removed from this event."
|
||||
msgstr "En bruger er blevet fjernet fra gruppen."
|
||||
msgstr "En metaegenskab er blevet fjernet fra denne begivenhed."
|
||||
|
||||
#: pretix/control/logdisplay.py:838
|
||||
#, fuzzy
|
||||
msgid "A meta property has been changed on this event."
|
||||
msgstr "En kvote er blevet ændret på arrangementsdatoen."
|
||||
msgstr "En metaegenskab er blevet ændret i forbindelse med denne begivenhed."
|
||||
|
||||
#: pretix/control/logdisplay.py:839
|
||||
msgid "The event settings have been changed."
|
||||
@@ -18515,31 +18418,27 @@ msgstr "Indstillingerne for download af billet er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:843
|
||||
msgid "The shop has been taken live."
|
||||
msgstr ""
|
||||
msgstr "Butikken er nu gået live."
|
||||
|
||||
#: pretix/control/logdisplay.py:844
|
||||
msgid "The shop has been taken offline."
|
||||
msgstr ""
|
||||
msgstr "Butikken er blevet taget offline."
|
||||
|
||||
#: pretix/control/logdisplay.py:845
|
||||
#, fuzzy
|
||||
msgid "The shop has been taken into test mode."
|
||||
msgstr "Bestillingen er blevet tilbagebetalt."
|
||||
msgstr "Butikken er nu sat i testtilstand."
|
||||
|
||||
#: pretix/control/logdisplay.py:846
|
||||
#, fuzzy
|
||||
msgid "The test mode has been disabled."
|
||||
msgstr "Den valgte dato er blevet slettet."
|
||||
msgstr "Testtilstanden er blevet deaktiveret."
|
||||
|
||||
#: pretix/control/logdisplay.py:847
|
||||
#, fuzzy
|
||||
msgid "The event has been created."
|
||||
msgstr "Arrangementsdatoen er blevet oprettet."
|
||||
msgstr "Begivenheden er blevet oprettet."
|
||||
|
||||
#: pretix/control/logdisplay.py:848
|
||||
#, fuzzy
|
||||
msgid "The event details have been changed."
|
||||
msgstr "Indstillingerne for arrangementet er blevet ændret."
|
||||
msgstr "Begivenhedens oplysninger er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:850
|
||||
msgid "An answer option has been added to the question."
|
||||
@@ -18582,10 +18481,9 @@ msgid "The check-in list has been changed."
|
||||
msgstr "Tjek-ind-listen er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:869
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Check-in list"
|
||||
#, python-brace-format
|
||||
msgid "Check-in list {val}"
|
||||
msgstr "Tjek-ind-liste"
|
||||
msgstr "Tjek-ind-liste {val}"
|
||||
|
||||
#: pretix/control/logdisplay.py:896
|
||||
msgid "The product has been created."
|
||||
@@ -18596,9 +18494,8 @@ msgid "The product has been changed."
|
||||
msgstr "Produktet er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:898
|
||||
#, fuzzy
|
||||
msgid "The product has been reordered."
|
||||
msgstr "Produktet er blevet oprettet."
|
||||
msgstr "Produktet er blevet genbestilt."
|
||||
|
||||
#: pretix/control/logdisplay.py:899
|
||||
msgid "The product has been deleted."
|
||||
@@ -18617,37 +18514,28 @@ msgid "An add-on has been changed on this product."
|
||||
msgstr "En tilføjelse er blevet ændret på dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:903
|
||||
#, fuzzy
|
||||
msgid "A bundled item has been added to this product."
|
||||
msgstr "En tilføjelse er blevet føjet til dette produkt."
|
||||
msgstr "Der er blevet tilføjet en medfølgende vare til dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:904
|
||||
#, fuzzy
|
||||
msgid "A bundled item has been removed from this product."
|
||||
msgstr "En tilføjelse er blevet fjernet fra dette produkt."
|
||||
msgstr "En medfølgende vare er blevet fjernet fra dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:905
|
||||
#, fuzzy
|
||||
msgid "A bundled item has been changed on this product."
|
||||
msgstr "En tilføjelse er blevet ændret på dette produkt."
|
||||
msgstr "En medfølgende vare er blevet ændret for dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:906
|
||||
#, fuzzy
|
||||
#| msgid "An add-on has been added to this product."
|
||||
msgid "A program time has been added to this product."
|
||||
msgstr "En tilføjelse er blevet føjet til dette produkt."
|
||||
msgstr "Der er blevet tilføjet en programtid til dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:907
|
||||
#, fuzzy
|
||||
#| msgid "An add-on has been changed on this product."
|
||||
msgid "A program time has been changed on this product."
|
||||
msgstr "En tilføjelse er blevet ændret på dette produkt."
|
||||
msgstr "En programtid for dette produkt er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:908
|
||||
#, fuzzy
|
||||
#| msgid "An add-on has been removed from this product."
|
||||
msgid "A program time has been removed from this product."
|
||||
msgstr "En tilføjelse er blevet fjernet fra dette produkt."
|
||||
msgstr "En programtid er blevet fjernet fra dette produkt."
|
||||
|
||||
#: pretix/control/logdisplay.py:915
|
||||
#, python-brace-format
|
||||
@@ -18665,9 +18553,9 @@ msgid "The variation \"{value}\" has been changed."
|
||||
msgstr "Varianten \"{value}\" er blevet ændret."
|
||||
|
||||
#: pretix/control/logdisplay.py:934
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Payment {local_id} has been confirmed."
|
||||
msgstr "Betalingsmetoden er blevet ændret."
|
||||
msgstr "Betalingen {local_id} er blevet bekræftet."
|
||||
|
||||
#: pretix/control/logdisplay.py:935
|
||||
#, fuzzy, python-brace-format
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-27 14:47+0000\n"
|
||||
"PO-Revision-Date: 2026-01-23 15:00+0000\n"
|
||||
"Last-Translator: Vajda Tamás <vajda.tamas@szwg.hu>\n"
|
||||
"PO-Revision-Date: 2026-06-18 21:00+0000\n"
|
||||
"Last-Translator: Szurofka Márton <szurofka.marton@sze.hu>\n"
|
||||
"Language-Team: Hungarian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
"js/hu/>\n"
|
||||
"Language: hu\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
"X-Generator: Weblate 2026.6.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -31,16 +31,16 @@ msgstr "Megjegyzés:"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
|
||||
msgid "PayPal"
|
||||
msgstr ""
|
||||
msgstr "PayPal"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
|
||||
msgid "Venmo"
|
||||
msgstr ""
|
||||
msgstr "Venmo"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
|
||||
#: pretix/static/pretixpresale/js/walletdetection.js:38
|
||||
msgid "Apple Pay"
|
||||
msgstr ""
|
||||
msgstr "Apple Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
|
||||
msgid "Itaú"
|
||||
@@ -56,7 +56,7 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
|
||||
msgid "PayPal Pay Later"
|
||||
msgstr ""
|
||||
msgstr "PayPal Későbbi Fizetés"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
|
||||
msgid "iDEAL | Wero"
|
||||
@@ -148,7 +148,7 @@ msgstr "A fizetés megerősítése…"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:254
|
||||
msgid "Payment method unavailable"
|
||||
msgstr ""
|
||||
msgstr "Fizetésimód nem elérhető"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:63
|
||||
@@ -163,12 +163,12 @@ msgstr "Kifizetett megrendelések"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Résztvevők (megrendelve)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Résztvevők (fizetve)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
@@ -187,18 +187,13 @@ msgid "Contacting your bank …"
|
||||
msgstr "Kapcsolatfelvétel a bankjával…"
|
||||
|
||||
#: pretix/static/lightbox/js/lightbox.js:96
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close"
|
||||
msgid "close"
|
||||
msgstr "Bezárás"
|
||||
msgstr "bezárás"
|
||||
|
||||
#: pretix/static/pretixbase/js/addressform.js:108
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:529
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "required"
|
||||
msgstr "A kosár lejárt"
|
||||
msgstr "a kosár lejárt"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:13
|
||||
#, fuzzy
|
||||
@@ -276,6 +271,8 @@ msgstr ""
|
||||
#: pretix/static/pretixbase/js/asynctask.js:286
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr ""
|
||||
"Amennyiben ez több időt vesz igénybe, mint néhány perc, kérjük jelezze "
|
||||
"felénk."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:341
|
||||
msgid "Close message"
|
||||
@@ -302,26 +299,20 @@ msgid "Group of objects"
|
||||
msgstr "tárgy csoport"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:909
|
||||
#, fuzzy
|
||||
#| msgid "Text object"
|
||||
msgid "Text object (deprecated)"
|
||||
msgstr "Szöveg"
|
||||
msgstr "Szöveg elem (elavult)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:911
|
||||
#, fuzzy
|
||||
#| msgid "Text object"
|
||||
msgid "Text box"
|
||||
msgstr "Szöveg"
|
||||
msgstr "Szövegdoboz"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:913
|
||||
msgid "Barcode area"
|
||||
msgstr "Vonalkód terület"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:915
|
||||
#, fuzzy
|
||||
#| msgid "Barcode area"
|
||||
msgid "Image area"
|
||||
msgstr "Vonalkód terület"
|
||||
msgstr "Kép helye"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:917
|
||||
msgid "Powered by pretix"
|
||||
@@ -361,19 +352,16 @@ msgid "Unknown error."
|
||||
msgstr "Ismeretlen hiba."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:310
|
||||
#, fuzzy
|
||||
#| msgid "Your color has great contrast and is very easy to read!"
|
||||
msgid "Your color has great contrast and will provide excellent accessibility."
|
||||
msgstr "A választott színek remek kontrasztot adnak, és nagyon könnyű olvasni!"
|
||||
msgstr "A választott színek remek kontrasztot adnak, és nagyon könnyű olvasni."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:314
|
||||
#, fuzzy
|
||||
#| msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgid ""
|
||||
"Your color has decent contrast and is sufficient for minimum accessibility "
|
||||
"requirements."
|
||||
msgstr ""
|
||||
"A választott színek kontrasztja elégséges, és valószínűleg jól olvasható!"
|
||||
"A választott színek kontrasztja elégséges, és elegendő a minimum "
|
||||
"követelménynek."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:318
|
||||
msgid ""
|
||||
@@ -384,7 +372,7 @@ msgstr ""
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:446
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
msgid "Search query"
|
||||
msgstr ""
|
||||
msgstr "Keresési lekérdezés"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:464
|
||||
msgid "All"
|
||||
@@ -404,7 +392,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:845
|
||||
msgid "Invalid page number."
|
||||
msgstr ""
|
||||
msgstr "Helytelen oldalszám."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1003
|
||||
msgid "Use a different name internally"
|
||||
@@ -465,7 +453,7 @@ msgstr "A kosár lejárt"
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:58
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:84
|
||||
msgid "Your cart is about to expire."
|
||||
msgstr ""
|
||||
msgstr "Kosara tartalma hamarosan lejár."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:62
|
||||
#, fuzzy
|
||||
@@ -532,32 +520,32 @@ msgstr ""
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:16
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
msgstr "Mennyiség"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Decrease quantity"
|
||||
msgstr ""
|
||||
msgstr "Mennyiség csökkentése"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Increase quantity"
|
||||
msgstr ""
|
||||
msgstr "Mennyiség növelése"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
msgctxt "widget"
|
||||
msgid "Filter events by"
|
||||
msgstr ""
|
||||
msgstr "Események szűrése a következő szerint"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
msgctxt "widget"
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Szűrés"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Ár"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#, javascript-format
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-27 15:47+0000\n"
|
||||
"PO-Revision-Date: 2025-10-17 16:55+0000\n"
|
||||
"Last-Translator: fd <fd@denkena-consulting.com>\n"
|
||||
"PO-Revision-Date: 2026-06-20 17:00+0000\n"
|
||||
"Last-Translator: Nikita Mitasov <me@ch4og.com>\n"
|
||||
"Language-Team: Russian <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"ru/>\n"
|
||||
"Language: ru\n"
|
||||
@@ -18,7 +18,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.13.3\n"
|
||||
"X-Generator: Weblate 2026.6.1\n"
|
||||
|
||||
#: htmlcov/d_daa1541d0cbf5e2b_dashboards_py.html:670
|
||||
#: pretix/control/templates/pretixcontrol/events/index.html:166
|
||||
@@ -53,7 +53,7 @@ msgstr "В продаже"
|
||||
|
||||
#: pretix/_base_settings.py:89
|
||||
msgid "English"
|
||||
msgstr "английский язык"
|
||||
msgstr "Английский язык"
|
||||
|
||||
#: pretix/_base_settings.py:90
|
||||
msgid "German"
|
||||
@@ -466,7 +466,7 @@ msgstr "Этот пользователь уже имеет разрешения
|
||||
#: pretix/api/views/cart.py:209
|
||||
msgid ""
|
||||
"The specified voucher has already been used the maximum number of times."
|
||||
msgstr "Указанный ваучер уже использован максимальное количество раз."
|
||||
msgstr "Указанный промокод уже использован максимальное количество раз."
|
||||
|
||||
#: pretix/api/views/checkin.py:645 pretix/api/views/checkin.py:652
|
||||
msgid "Medium connected to other event"
|
||||
@@ -565,65 +565,50 @@ msgid "Refund of payment failed"
|
||||
msgstr "Возврат платежа не удался"
|
||||
|
||||
#: pretix/api/webhooks.py:359
|
||||
#, fuzzy
|
||||
#| msgctxt "checkoutflow"
|
||||
#| msgid "Order confirmed"
|
||||
msgid "Payment confirmed"
|
||||
msgstr "Заказ подтверждён"
|
||||
msgstr "Платёж подтверждён"
|
||||
|
||||
#: pretix/api/webhooks.py:363
|
||||
msgid "Order approved"
|
||||
msgstr ""
|
||||
msgstr "Заказ подтверждён"
|
||||
|
||||
#: pretix/api/webhooks.py:367
|
||||
msgid "Order denied"
|
||||
msgstr ""
|
||||
msgstr "Заказ отклонён"
|
||||
|
||||
#: pretix/api/webhooks.py:371
|
||||
#, fuzzy
|
||||
#| msgid "Order date"
|
||||
msgid "Order deleted"
|
||||
msgstr "Дата заказа"
|
||||
msgstr "Заказ удалён"
|
||||
|
||||
#: pretix/api/webhooks.py:375
|
||||
msgid "Ticket checked in"
|
||||
msgstr ""
|
||||
msgstr "Билет использован"
|
||||
|
||||
#: pretix/api/webhooks.py:379
|
||||
msgid "Ticket check-in reverted"
|
||||
msgstr ""
|
||||
msgstr "Использование билета отменено"
|
||||
|
||||
#: pretix/api/webhooks.py:383
|
||||
#, fuzzy
|
||||
#| msgid "Event date"
|
||||
msgid "Event created"
|
||||
msgstr "Дата мероприятия"
|
||||
msgstr "Мероприятие создано"
|
||||
|
||||
#: pretix/api/webhooks.py:387
|
||||
#, fuzzy
|
||||
#| msgid "Event date range"
|
||||
msgid "Event details changed"
|
||||
msgstr "Диапазон дат мероприятия"
|
||||
msgstr "Данные о мероприятии изменились"
|
||||
|
||||
#: pretix/api/webhooks.py:391
|
||||
#, fuzzy
|
||||
#| msgid "Event date"
|
||||
msgid "Event deleted"
|
||||
msgstr "Дата мероприятия"
|
||||
msgstr "Мероприятие удалено"
|
||||
|
||||
#: pretix/api/webhooks.py:395
|
||||
#, fuzzy
|
||||
#| msgid "Event begin date and time"
|
||||
msgctxt "subevent"
|
||||
msgid "Event series date added"
|
||||
msgstr "Дата и время начала мероприятия"
|
||||
msgstr "Добавлена дата серии мероприятий"
|
||||
|
||||
#: pretix/api/webhooks.py:399
|
||||
#, fuzzy
|
||||
#| msgid "Event date range"
|
||||
msgctxt "subevent"
|
||||
msgid "Event series date changed"
|
||||
msgstr "Диапазон дат мероприятия"
|
||||
msgstr "Изменена дата серии мероприятий"
|
||||
|
||||
#: pretix/api/webhooks.py:403
|
||||
#, fuzzy
|
||||
@@ -866,14 +851,13 @@ msgid "<a {a_attr}>powered by {name} based on pretix</a>"
|
||||
msgstr "на базе <a %(a_attr)s>pretix</a>"
|
||||
|
||||
#: pretix/base/context.py:55
|
||||
#, fuzzy, python-format
|
||||
#| msgid "<a %(a_attr)s>event ticketing powered by pretix</a>"
|
||||
#, python-format
|
||||
msgid "<a %(a_attr)s>ticketing powered by pretix</a>"
|
||||
msgstr "<a %(a_attr)s>event ticketing powered by pretix</a>"
|
||||
msgstr "<a %(a_attr)s>продажа билетов на базе pretix</a>"
|
||||
|
||||
#: pretix/base/context.py:64
|
||||
msgid "source code"
|
||||
msgstr "Промокод"
|
||||
msgstr "исходный код"
|
||||
|
||||
#: pretix/base/customersso/oidc.py:61
|
||||
#, python-brace-format
|
||||
@@ -2777,10 +2761,8 @@ msgid "Voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:656
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code used:"
|
||||
msgid "Voucher budget usage"
|
||||
msgstr "Использованный код ваучера:"
|
||||
msgstr "Использовано по промокоду"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:657
|
||||
#, fuzzy
|
||||
@@ -3176,7 +3158,7 @@ msgstr "Заказы в ожидании"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:1209
|
||||
msgid "Blocking vouchers"
|
||||
msgstr "Блокирующие ваучеры"
|
||||
msgstr "Блокирующие промокоды"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:1210 pretix/control/views/item.py:1149
|
||||
msgid "Current user's carts"
|
||||
@@ -4606,7 +4588,7 @@ msgstr "Архивные события не найдены."
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:50 pretix/base/models/vouchers.py:491
|
||||
msgid "A voucher with this code already exists."
|
||||
msgstr "Ваучер с этим кодом уже существует."
|
||||
msgstr "Промокод с этим кодом уже существует."
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:68 pretix/base/models/memberships.py:57
|
||||
#: pretix/base/models/vouchers.py:199 pretix/control/views/vouchers.py:121
|
||||
@@ -4708,7 +4690,7 @@ msgstr ""
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:334 pretix/base/models/vouchers.py:300
|
||||
msgid "Shows hidden products that match this voucher"
|
||||
msgstr "Показывает скрытые продукты, которые соответствуют этому ваучеру"
|
||||
msgstr "Показывает скрытые продукты, которые соответствуют этому промокоду"
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:343 pretix/base/models/vouchers.py:304
|
||||
msgid "Offer all add-on products for free when redeeming this voucher"
|
||||
@@ -4960,11 +4942,8 @@ msgid "Order not approved"
|
||||
msgstr "Срок действия заказа истёк"
|
||||
|
||||
#: pretix/base/models/checkin.py:367
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "This voucher is not valid for this event date."
|
||||
msgid "Ticket not valid at this time"
|
||||
msgstr "Этот ваучер не действителен на эту дату мероприятия."
|
||||
msgstr "Билет не действителен в это время"
|
||||
|
||||
#: pretix/base/models/checkin.py:368
|
||||
#, fuzzy
|
||||
@@ -7761,9 +7740,9 @@ msgid ""
|
||||
"same value for multiple vouchers, you can get statistics on how many of them "
|
||||
"have been redeemed etc."
|
||||
msgstr ""
|
||||
"Вы можете использовать это поле для группировки нескольких ваучеров. Если вы "
|
||||
"введёте одно и то же значение для нескольких ваучеров, вы сможете получить "
|
||||
"статистику о том, сколько из них было использовано и т. д."
|
||||
"Вы можете использовать это поле для группировки нескольких промокодов. Если "
|
||||
"вы введёте одно и то же значение для нескольких промокодов, вы сможете "
|
||||
"получить статистику о том, сколько из них было использовано и т. д."
|
||||
|
||||
#: pretix/base/models/vouchers.py:316 pretix/base/permissions.py:242
|
||||
#: pretix/control/navigation.py:289
|
||||
@@ -7808,7 +7787,7 @@ msgstr "Этот вариант не относится к этому проду
|
||||
#: pretix/base/models/vouchers.py:358
|
||||
msgid "It is currently not possible to create vouchers for add-on products."
|
||||
msgstr ""
|
||||
"В настоящее время невозможно создать ваучеры для дополнительных продуктов."
|
||||
"В настоящее время невозможно создать промокоды для дополнительных продуктов."
|
||||
|
||||
#: pretix/base/models/vouchers.py:360 pretix/base/models/vouchers.py:472
|
||||
#, fuzzy
|
||||
@@ -7824,7 +7803,7 @@ msgid ""
|
||||
"This voucher has already been redeemed %(redeemed)s times. You cannot reduce "
|
||||
"the maximum number of usages below this number."
|
||||
msgstr ""
|
||||
"Этот ваучер уже был использован %(redeemed)s раз. Вы не можете уменьшить "
|
||||
"Этот промокод уже был использован %(redeemed)s раз. Вы не можете уменьшить "
|
||||
"максимальное количество использований ниже этого числа."
|
||||
|
||||
#: pretix/base/models/vouchers.py:379
|
||||
@@ -7843,7 +7822,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"If you want this voucher to block quota, you need to select a specific date."
|
||||
msgstr ""
|
||||
"Если вы хотите, чтобы этот ваучер блокировал квоту, вы должны выбрать "
|
||||
"Если вы хотите, чтобы этот промокод блокировал квоту, вы должны выбрать "
|
||||
"конкретную дату."
|
||||
|
||||
#: pretix/base/models/vouchers.py:387
|
||||
@@ -7857,7 +7836,7 @@ msgid ""
|
||||
"You cannot create a voucher that blocks quota as the selected product or "
|
||||
"quota is currently sold out or completely reserved."
|
||||
msgstr ""
|
||||
"Вы не можете создать ваучер, который блокирует квоту, поскольку выбранный "
|
||||
"Вы не можете создать промокод, который блокирует квоту, поскольку выбранный "
|
||||
"продукт или квота в настоящее время распроданы или полностью зарезервированы."
|
||||
|
||||
#: pretix/base/models/vouchers.py:507
|
||||
@@ -7879,7 +7858,7 @@ msgstr "В листе ожидания с"
|
||||
|
||||
#: pretix/base/models/waitinglist.py:84
|
||||
msgid "Assigned voucher"
|
||||
msgstr "Присвоенный ваучер"
|
||||
msgstr "Присвоенный промокод"
|
||||
|
||||
#: pretix/base/models/waitinglist.py:93
|
||||
msgid "The product the user waits for."
|
||||
@@ -7913,7 +7892,7 @@ msgstr "Эта запись анонимизирована и больше не
|
||||
|
||||
#: pretix/base/models/waitinglist.py:197
|
||||
msgid "A voucher has already been sent to this person."
|
||||
msgstr "Ваучер уже отправлен данному лицу."
|
||||
msgstr "Промокод уже отправлен данному лицу."
|
||||
|
||||
#: pretix/base/models/waitinglist.py:208
|
||||
#, python-brace-format
|
||||
@@ -8083,8 +8062,8 @@ msgid ""
|
||||
"You entered a voucher instead of a gift card. Vouchers can only be entered "
|
||||
"on the first page of the shop below the product selection."
|
||||
msgstr ""
|
||||
"Вы ввели ваучер вместо подарочного сертификата. Ваучеры можно вводить только "
|
||||
"на первой странице магазина под ассортиментом продуктов."
|
||||
"Вы ввели промокод вместо подарочного сертификата. Промокод можно вводить "
|
||||
"только на первой странице магазина под ассортиментом продуктов."
|
||||
|
||||
#: pretix/base/payment.py:151
|
||||
msgid "This gift card is not known."
|
||||
@@ -9373,7 +9352,7 @@ msgstr "Введённая цена слишком высока."
|
||||
|
||||
#: pretix/base/services/cart.py:163
|
||||
msgid "This voucher code is not known in our database."
|
||||
msgstr "Этот код ваучера не известен в нашей базе данных."
|
||||
msgstr "Этот промокод не известен в нашей базе данных."
|
||||
|
||||
#: pretix/base/services/cart.py:165
|
||||
#, fuzzy, python-format
|
||||
@@ -9407,7 +9386,7 @@ msgstr[2] ""
|
||||
msgid ""
|
||||
"This voucher code has already been used the maximum number of times allowed."
|
||||
msgstr ""
|
||||
"Этот код ваучера уже был использован максимально допустимое количество раз."
|
||||
"Этот промокод уже был использован максимально допустимое количество раз."
|
||||
|
||||
#: pretix/base/services/cart.py:178
|
||||
#, python-format
|
||||
@@ -9417,15 +9396,16 @@ msgid ""
|
||||
"or that you tried to redeem it before but did not complete the checkout "
|
||||
"process. You can try to use it again in %d minutes."
|
||||
msgstr ""
|
||||
"Этот код ваучера в настоящее время заблокирован, так как он уже содержится в "
|
||||
"Этот промокод в настоящее время заблокирован, так как он уже содержится в "
|
||||
"корзине. Это может означать, что кто-то другой сейчас использует этот "
|
||||
"ваучер, или что вы пытались его использовать ранее, но не завершили процесс "
|
||||
"оформления. Вы можете попробовать использовать его снова через %d минут."
|
||||
"промокод, или что вы пытались его использовать ранее, но не завершили "
|
||||
"процесс оформления. Вы можете попробовать использовать его снова через %d "
|
||||
"минут."
|
||||
|
||||
#: pretix/base/services/cart.py:183
|
||||
#, python-format
|
||||
msgid "This voucher code can only be redeemed %d more times."
|
||||
msgstr "Этот код ваучера можно использовать только ещё %d раз."
|
||||
msgstr "Этот промокод можно использовать ещё %d раз."
|
||||
|
||||
#: pretix/base/services/cart.py:184
|
||||
msgid ""
|
||||
@@ -9438,23 +9418,20 @@ msgid ""
|
||||
"You already used this voucher code. Remove the associated line from your "
|
||||
"cart if you want to use it for a different product."
|
||||
msgstr ""
|
||||
"Вы уже использовали этот код ваучера. Удалите связанную строку из вашей "
|
||||
"Вы уже использовали этот промокод. Удалите связанную строку из вашей "
|
||||
"корзины, если вы хотите использовать его для другого продукта."
|
||||
|
||||
#: pretix/base/services/cart.py:189
|
||||
msgid "This voucher is expired."
|
||||
msgstr "Срок действия этого ваучера истёк."
|
||||
msgstr "Срок действия этого промокода истёк."
|
||||
|
||||
#: pretix/base/services/cart.py:190
|
||||
msgid "This voucher is not valid for this product."
|
||||
msgstr "Этот ваучер недействителен для данного продукта."
|
||||
msgstr "Этот промокод недействителен для данного продукта."
|
||||
|
||||
#: pretix/base/services/cart.py:191
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "This voucher is not valid for this event date."
|
||||
msgid "This voucher is not valid for this seat."
|
||||
msgstr "Этот ваучер не действителен на эту дату мероприятия."
|
||||
msgstr "Этот промокод не действителен для данного места."
|
||||
|
||||
#: pretix/base/services/cart.py:193
|
||||
msgid ""
|
||||
@@ -9466,16 +9443,17 @@ msgstr ""
|
||||
#: pretix/base/services/cart.py:198
|
||||
msgid "Your voucher is valid for a product that is currently not for sale."
|
||||
msgstr ""
|
||||
"Ваш ваучер действителен для продукта, который в настоящее время не продаётся."
|
||||
"Ваш промокод действителен для продукта, который в настоящее время не "
|
||||
"продаётся."
|
||||
|
||||
#: pretix/base/services/cart.py:199
|
||||
msgctxt "subevent"
|
||||
msgid "This voucher is not valid for this event date."
|
||||
msgstr "Этот ваучер не действителен на эту дату мероприятия."
|
||||
msgstr "Этот промокод не действителен на эту дату мероприятия."
|
||||
|
||||
#: pretix/base/services/cart.py:200
|
||||
msgid "You need a valid voucher code to order this product."
|
||||
msgstr "Необходим действительный код ваучера для заказа этого продукта."
|
||||
msgstr "Необходим действительный промокод для заказа этого продукта."
|
||||
|
||||
#: pretix/base/services/cart.py:201
|
||||
msgctxt "subevent"
|
||||
@@ -9578,8 +9556,8 @@ msgid ""
|
||||
"You entered a gift card instead of a voucher. Gift cards can be entered "
|
||||
"later on when you're asked for your payment details."
|
||||
msgstr ""
|
||||
"Вы ввели подарочный сертификат вместо ваучера. Подарочные сертификаты можно "
|
||||
"ввести позже, когда вас попросят указать реквизиты для оплаты."
|
||||
"Вы ввели подарочный сертификат вместо промокода. Подарочные сертификаты "
|
||||
"можно ввести позже, когда вас попросят указать реквизиты для оплаты."
|
||||
|
||||
#: pretix/base/services/cart.py:224
|
||||
msgid ""
|
||||
@@ -9746,11 +9724,9 @@ msgid "This order is not yet approved."
|
||||
msgstr "Этот заказ не ожидает утверждения."
|
||||
|
||||
#: pretix/base/services/checkin.py:999 pretix/base/services/checkin.py:1003
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "This voucher is not valid for this event date."
|
||||
#, python-brace-format
|
||||
msgid "This ticket is only valid after {datetime}."
|
||||
msgstr "Этот ваучер не действителен на эту дату мероприятия."
|
||||
msgstr "Этот билет действителен только после {datetime}."
|
||||
|
||||
#: pretix/base/services/checkin.py:1013 pretix/base/services/checkin.py:1017
|
||||
#, fuzzy, python-brace-format
|
||||
@@ -9908,6 +9884,12 @@ msgid ""
|
||||
"We are sending this email because you configured us to do so in your event "
|
||||
"settings."
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"новый счет для заказа {order} на {event} создан, смотрите вложение.\n"
|
||||
"\n"
|
||||
"Вы получили это письмо, поскольку в настройках мероприятия была включена "
|
||||
"отправка таких уведомлений."
|
||||
|
||||
#: pretix/base/services/mail.py:144
|
||||
#, fuzzy
|
||||
@@ -10163,8 +10145,8 @@ msgid ""
|
||||
"The voucher code used for one of the items in your cart is not known in our "
|
||||
"database."
|
||||
msgstr ""
|
||||
"Код ваучера, использованный для одной из позиций в вашей корзине, неизвестен "
|
||||
"в нашей базе данных."
|
||||
"Промокод, использованный для одной из позиций в вашей корзине, неизвестен в "
|
||||
"нашей базе данных."
|
||||
|
||||
#: pretix/base/services/orders.py:173
|
||||
msgid ""
|
||||
@@ -10172,30 +10154,24 @@ msgid ""
|
||||
"used the maximum number of times allowed. We removed this item from your "
|
||||
"cart."
|
||||
msgstr ""
|
||||
"Код ваучера, использованный для одной из позиций в вашей корзине, уже был "
|
||||
"Промокод, использованный для одной из позиций в вашей корзине, уже был "
|
||||
"использован максимально допустимое количество раз. Мы удалили эту позицию из "
|
||||
"вашей корзины."
|
||||
|
||||
#: pretix/base/services/orders.py:177
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The voucher code used for one of the items in your cart has already been "
|
||||
#| "used the maximum number of times allowed. We removed this item from your "
|
||||
#| "cart."
|
||||
msgid ""
|
||||
"The voucher code used for one of the items in your cart has already been too "
|
||||
"often. We adjusted the price of the item in your cart."
|
||||
msgstr ""
|
||||
"Код ваучера, использованный для одной из позиций в вашей корзине, уже был "
|
||||
"использован максимально допустимое количество раз. Мы удалили эту позицию из "
|
||||
"вашей корзины."
|
||||
"Промокод, применённый к одному из товаров в вашей корзине, был использован "
|
||||
"слишком много раз. Мы скорректировали цену товара в вашей корзине."
|
||||
|
||||
#: pretix/base/services/orders.py:181
|
||||
msgid ""
|
||||
"The voucher code used for one of the items in your cart is expired. We "
|
||||
"removed this item from your cart."
|
||||
msgstr ""
|
||||
"Срок действия кода ваучера, использованного для одной из позиций в вашей "
|
||||
"Срок действия промокода, использованного для одной из позиций в вашей "
|
||||
"корзине, истёк. Мы удалили эту позицию из вашей корзины."
|
||||
|
||||
#: pretix/base/services/orders.py:184
|
||||
@@ -10203,14 +10179,12 @@ msgid ""
|
||||
"The voucher code used for one of the items in your cart is not valid for "
|
||||
"this item. We removed this item from your cart."
|
||||
msgstr ""
|
||||
"Код ваучера, использованный для одной из позиций в вашей корзине, "
|
||||
"Промокод, использованный для одной из позиций в вашей корзине, "
|
||||
"недействителен для этой позиции. Мы удалили эту позицию из вашей корзины."
|
||||
|
||||
#: pretix/base/services/orders.py:186
|
||||
#, fuzzy
|
||||
#| msgid "You need a valid voucher code to order this product."
|
||||
msgid "You need a valid voucher code to order one of the products."
|
||||
msgstr "Необходим действительный код ваучера для заказа этого продукта."
|
||||
msgstr "Необходим действительный промокод для одного из продуктов."
|
||||
|
||||
#: pretix/base/services/orders.py:187
|
||||
msgid ""
|
||||
@@ -12221,6 +12195,16 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"вы получили это письмо, потому что запросили ссылку\n"
|
||||
"на ваш заказ для мероприятия {event}.\n"
|
||||
"\n"
|
||||
"Вы можете изменить данные заказа и просмотреть его статус по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2461
|
||||
#, python-brace-format
|
||||
@@ -12240,6 +12224,15 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"кто-то запросил список ваших заказов для мероприятия {event}.\n"
|
||||
"Список заказов::\n"
|
||||
"\n"
|
||||
"{orders}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2481
|
||||
#, python-brace-format
|
||||
@@ -12269,6 +12262,17 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"ваш заказ для мероприятия {event} прошел успешно. Поскольку ваш заказ "
|
||||
"состоит только из бесплатных позиций,\n"
|
||||
"оплата не требуется.\n"
|
||||
"\n"
|
||||
"Вы можете изменить детали заказа и посмотреть его статус по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2518
|
||||
#, python-brace-format
|
||||
@@ -12285,6 +12289,18 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"мы успешно получили ваш заказ для мероприятия {event}. Поскольку вы "
|
||||
"заказали\n"
|
||||
"товар, требующий подтверждения со стороны организатора, просим вас\n"
|
||||
"подождать нашего следующего письма.\n"
|
||||
"\n"
|
||||
"Вы можете изменить данные заказа и просмотреть его статус по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2536
|
||||
#, python-brace-format
|
||||
@@ -12303,6 +12319,19 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"мы успешно получили ваш заказ на сумму {total_with_currency} для мероприятия "
|
||||
"{event}.\n"
|
||||
"Пожалуйста, завершите оплату до {expire_date}.\n"
|
||||
"\n"
|
||||
"{payment_info}\n"
|
||||
"\n"
|
||||
"Вы можете изменить данные заказа и просмотреть его статус по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2554
|
||||
#, fuzzy
|
||||
@@ -12354,6 +12383,15 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"ваш заказ для мероприятия {event} был изменен.\n"
|
||||
"\n"
|
||||
"Вы можете посмотреть статус своего заказа по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2614
|
||||
#, python-brace-format
|
||||
@@ -12375,6 +12413,17 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"мы успешно получили вашу оплату за мероприятие {event}. Спасибо!\n"
|
||||
"\n"
|
||||
"{payment_info}\n"
|
||||
"\n"
|
||||
"Вы можете изменить данные заказа и просмотреть его статус по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2636
|
||||
#, python-brace-format
|
||||
@@ -12426,6 +12475,17 @@ msgid ""
|
||||
"Best regards, \n"
|
||||
"Your {event} team"
|
||||
msgstr ""
|
||||
"Здравствуйте,\n"
|
||||
"\n"
|
||||
"мы не получили полной оплаты вашего заказа для мероприятия {event}.\n"
|
||||
"Обратите внимание: мы можем гарантировать ваш заказ только в том случае,\n"
|
||||
"если оплата поступит до {expire_date}.\n"
|
||||
"\n"
|
||||
"Информацию об оплате и статус заказа можно посмотреть по ссылке:\n"
|
||||
"{url}\n"
|
||||
"\n"
|
||||
"С уважением, \n"
|
||||
"Команда мероприятия {event}"
|
||||
|
||||
#: pretix/base/settings.py:2685
|
||||
#, python-brace-format
|
||||
@@ -13648,10 +13708,8 @@ msgid "created by"
|
||||
msgstr "создано"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:34
|
||||
#, fuzzy
|
||||
#| msgid "Bancontact"
|
||||
msgid "Contact:"
|
||||
msgstr "Bancontact"
|
||||
msgstr "Связаться:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:54
|
||||
#, fuzzy, python-format
|
||||
@@ -13684,10 +13742,8 @@ msgstr ""
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:136
|
||||
#: pretix/presale/templates/pretixpresale/event/base.html:223
|
||||
#: pretix/presale/templates/pretixpresale/organizers/base.html:101
|
||||
#, fuzzy
|
||||
#| msgid "Bancontact"
|
||||
msgid "Contact"
|
||||
msgstr "Bancontact"
|
||||
msgstr "Связаться"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/shred_completed.txt:2
|
||||
#, python-format
|
||||
@@ -13758,16 +13814,17 @@ msgid "Proceed to %(host)s"
|
||||
msgstr "Приступить к оформлению заказа"
|
||||
|
||||
#: pretix/base/templates/source.html:5 pretix/base/templates/source.html:9
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code"
|
||||
msgid "Source code"
|
||||
msgstr "Код ваучера"
|
||||
msgstr "Исходный код"
|
||||
|
||||
#: pretix/base/templates/source.html:10
|
||||
msgid ""
|
||||
"This site is powered by free software. If you want to read the license terms "
|
||||
"or obtain the source code, follow these links or instructions:"
|
||||
msgstr ""
|
||||
"Этот сайт работает на свободном программном обеспечении. Если вы хотите "
|
||||
"ознакомиться с условиями лицензии или получить исходный код, перейдите по "
|
||||
"следующим ссылкам или следуйте инструкциям:"
|
||||
|
||||
#: pretix/base/ticketoutput.py:182
|
||||
#, fuzzy
|
||||
@@ -15702,6 +15759,7 @@ msgid ""
|
||||
"This installation of pretix includes changes or extensions made to the "
|
||||
"source code."
|
||||
msgstr ""
|
||||
"Данная установка pretix содержит изменения или расширения исходного кода."
|
||||
|
||||
#: pretix/control/forms/global_settings.py:162
|
||||
msgid "Usage of pretix"
|
||||
@@ -15792,10 +15850,8 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/forms/global_settings.py:217
|
||||
#, fuzzy
|
||||
#| msgid "Your registration"
|
||||
msgid "Source code instructions"
|
||||
msgstr "Ваша регистрация"
|
||||
msgstr "Инструкции для получения исходного кода"
|
||||
|
||||
#: pretix/control/forms/global_settings.py:219
|
||||
msgid ""
|
||||
@@ -16761,10 +16817,8 @@ msgid "An medium with this type and identifier is already registered."
|
||||
msgstr "Ваучер с этим кодом уже существует."
|
||||
|
||||
#: pretix/control/forms/organizer.py:1059
|
||||
#, fuzzy
|
||||
#| msgid "A voucher with this code already exists."
|
||||
msgid "An account with this customer ID is already registered."
|
||||
msgstr "Ваучер с этим кодом уже существует."
|
||||
msgstr "Аккаунт с таким ID клиента уже существует."
|
||||
|
||||
#: pretix/control/forms/organizer.py:1076
|
||||
#: pretix/control/templates/pretixcontrol/organizers/customer.html:62
|
||||
@@ -16887,10 +16941,8 @@ msgid "The selected organizer has already been invited."
|
||||
msgstr "Выбранный организатор не найден."
|
||||
|
||||
#: pretix/control/forms/organizer.py:1379
|
||||
#, fuzzy
|
||||
#| msgid "A voucher with this code already exists."
|
||||
msgid "A sales channel with the same identifier already exists."
|
||||
msgstr "Ваучер с этим кодом уже существует."
|
||||
msgstr "Канал продаж с таким идентификатором уже существует."
|
||||
|
||||
#: pretix/control/forms/organizer.py:1391
|
||||
msgid "Events with active plugin"
|
||||
@@ -17173,10 +17225,8 @@ msgid "Only includes active products."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/forms/waitinglist.py:115
|
||||
#, fuzzy
|
||||
#| msgid "A voucher with this code already exists."
|
||||
msgid "A voucher for this waiting list entry was already sent out."
|
||||
msgstr "Ваучер с этим кодом уже существует."
|
||||
msgstr "Промокод для данного места в листе ожидания уже отправлен."
|
||||
|
||||
#: pretix/control/forms/waitinglist.py:125
|
||||
#, fuzzy
|
||||
@@ -18812,7 +18862,7 @@ msgstr "Оплата"
|
||||
#: pretix/presale/templates/pretixpresale/organizers/index.html:89
|
||||
#: pretix/presale/templates/pretixpresale/organizers/index.html:91
|
||||
msgid "Tickets"
|
||||
msgstr ""
|
||||
msgstr "Билеты"
|
||||
|
||||
#: pretix/control/navigation.py:97
|
||||
#: pretix/control/templates/pretixcontrol/event/tax.html:4
|
||||
@@ -22104,7 +22154,7 @@ msgstr ""
|
||||
#: pretix/control/templates/pretixcontrol/fragment_quota_box_paid.html:3
|
||||
#, python-format
|
||||
msgid "Currently available: %(num)s"
|
||||
msgstr ""
|
||||
msgstr "Сейчас доступно: %(num)s"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/global_license.html:8
|
||||
msgid ""
|
||||
@@ -24027,7 +24077,7 @@ msgstr "Начальная дата мероприятия"
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:498
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:55
|
||||
msgid "Voucher code used:"
|
||||
msgstr "Использованный код ваучера:"
|
||||
msgstr "Использованный промокод:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:500
|
||||
#, fuzzy, python-format
|
||||
@@ -27824,10 +27874,8 @@ msgstr ""
|
||||
#: pretix/control/templates/pretixcontrol/vouchers/import_start.html:6
|
||||
#: pretix/control/templates/pretixcontrol/vouchers/index.html:81
|
||||
#: pretix/control/templates/pretixcontrol/vouchers/index.html:94
|
||||
#, fuzzy
|
||||
#| msgid "Blocking vouchers"
|
||||
msgid "Import vouchers"
|
||||
msgstr "Блокирующие ваучеры"
|
||||
msgstr "Импорт промокодов"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/vouchers/index.html:10
|
||||
msgid ""
|
||||
@@ -30761,6 +30809,8 @@ msgid ""
|
||||
"After completing your purchase, we will ask you to transfer the money to the "
|
||||
"following bank account, using a personal reference code:"
|
||||
msgstr ""
|
||||
"После завершения покупки, мы попросим вас перевести оплату на следующий "
|
||||
"банковский счет, указав персональный код назначения платежа:"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:11
|
||||
msgid ""
|
||||
@@ -30771,23 +30821,27 @@ msgstr ""
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:14
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html:21
|
||||
msgid "Reference code (important):"
|
||||
msgstr ""
|
||||
msgstr "Код назначения платежа (важно):"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:30
|
||||
msgid "We will assign you a personal reference code in the next step."
|
||||
msgstr ""
|
||||
msgstr "Мы присвоим вам персональный код назначения платежа на следующем шаге."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:36
|
||||
msgid ""
|
||||
"We will assign you a personal reference code to use after you completed the "
|
||||
"order."
|
||||
msgstr ""
|
||||
"Мы присвоим вам персональный код назначения платежа после завершения "
|
||||
"оформления заказа."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:41
|
||||
msgid ""
|
||||
"After completing your purchase, we will ask you to transfer the money to our "
|
||||
"bank account, using a personal reference code."
|
||||
msgstr ""
|
||||
"После завершения покупки мы попросим вас перевести оплату на следующий "
|
||||
"банковский счёт, указав персональный код назначения платежа."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/control.html:6
|
||||
#, fuzzy
|
||||
@@ -30810,7 +30864,7 @@ msgstr "Общая сумма"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/control.html:38
|
||||
msgid "Reference code"
|
||||
msgstr ""
|
||||
msgstr "Код назначения платежа"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/import_assign.html:4
|
||||
msgid ""
|
||||
@@ -30949,7 +31003,7 @@ msgstr "Сумма:"
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html:34
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:30
|
||||
msgid "There is no further action required on this website."
|
||||
msgstr ""
|
||||
msgstr "Дальнейших действий на этом сайте не требуется."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html:35
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/pending.html:31
|
||||
@@ -34363,11 +34417,9 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/forms/renderers.py:66
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_voucher_form.html:14
|
||||
#, fuzzy
|
||||
#| msgid "expired"
|
||||
msgctxt "form"
|
||||
msgid "required"
|
||||
msgstr "истекло"
|
||||
msgstr "обязательно"
|
||||
|
||||
#: pretix/presale/ical.py:87 pretix/presale/ical.py:146
|
||||
#: pretix/presale/ical.py:182
|
||||
@@ -34559,10 +34611,8 @@ msgid "We're now trying to book these add-ons for you!"
|
||||
msgstr "Сейчас мы пытаемся забронировать эти дополнительные продукты для вас!"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:28
|
||||
#, fuzzy
|
||||
#| msgid "Additional information"
|
||||
msgid "Additional options for"
|
||||
msgstr "Дополнительная информация"
|
||||
msgstr "Дополнительные опции"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_addons.html:60
|
||||
#, fuzzy
|
||||
@@ -34614,10 +34664,8 @@ msgid "Cart expired"
|
||||
msgstr "Срок действия корзины истёк"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:36
|
||||
#, fuzzy
|
||||
#| msgid "Show variants"
|
||||
msgid "Show full cart"
|
||||
msgstr "Показать варианты"
|
||||
msgstr "Показать полную корзину"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:52
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:86
|
||||
@@ -34949,21 +34997,12 @@ msgstr[1] ""
|
||||
msgstr[2] ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "You can choose between %(min_count)s and %(max_count)s options from this "
|
||||
#| "category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] ""
|
||||
"Вы можете выбрать между вариантами %(min_count)s и %(max_count)s из этой "
|
||||
"категории."
|
||||
msgstr[1] ""
|
||||
"Вы можете выбрать между вариантами %(min_count)s и %(max_count)s из этой "
|
||||
"категории."
|
||||
msgstr[2] ""
|
||||
"Вы можете выбрать между вариантами %(min_count)s и %(max_count)s из этой "
|
||||
"категории."
|
||||
msgstr[0] "Вы можете выбрать не более %(max_count)s варианта из этой категории."
|
||||
msgstr[1] "Вы можете выбрать не более %(max_count)s вариантов из этой категории."
|
||||
msgstr[2] "Вы можете выбрать не более %(max_count)s вариантов из этой категории."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:34
|
||||
#, python-format
|
||||
@@ -35363,8 +35402,7 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:516
|
||||
#, fuzzy, python-format
|
||||
#| msgid "The items in your cart are reserved for you for %(minutes)s minutes."
|
||||
#, python-format
|
||||
msgid "The items in your cart are reserved for you for %(minutes)s minutes."
|
||||
msgstr "Позиции в вашей корзине зарезервированы для вас на %(minutes)s минут."
|
||||
|
||||
@@ -35413,7 +35451,7 @@ msgstr "Очистить корзину"
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:248
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher_form.html:16
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Использовать ваучер/промокод"
|
||||
msgstr "Использовать промокод"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart_box.html:71
|
||||
msgid "We're applying this voucher to your cart..."
|
||||
@@ -35422,7 +35460,7 @@ msgstr ""
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart_box.html:79
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_voucher_form.html:27
|
||||
msgid "Redeem voucher"
|
||||
msgstr "Использовать ваучер"
|
||||
msgstr "Активировать промокод"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_change_confirm.html:10
|
||||
#, fuzzy
|
||||
@@ -35746,7 +35784,7 @@ msgstr "Изменить цену для %(item)s"
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_quota_left.html:4
|
||||
#, python-format
|
||||
msgid "%(num)s currently available"
|
||||
msgstr ""
|
||||
msgstr "%(num)s доступно сейчас"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_subevent_calendar.html:5
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_subevent_calendar_week.html:5
|
||||
@@ -35999,32 +36037,23 @@ msgstr ""
|
||||
"завершения процесса."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:56
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please bookmark or save the link to this exact page if you want to access "
|
||||
#| "your order later. We also sent you an email containing the link to the "
|
||||
#| "address you specified."
|
||||
msgid ""
|
||||
"Please bookmark or save the link to this exact page if you want to access "
|
||||
"your order later. We also sent you an email to the address you specified "
|
||||
"containing the link to this page."
|
||||
msgstr ""
|
||||
"Пожалуйста, добавьте в закладки или сохраните ссылку именно на эту страницу, "
|
||||
"если вы хотите получить доступ к вашему заказу позже. Мы также отправили вам "
|
||||
"электронное письмо со ссылкой на указанный вами адрес."
|
||||
"Пожалуйста, сохраните закладку или ссылку на эту страницу, если вам "
|
||||
"потребуется доступ к заказу позже. Мы также отправили письмо на указанный "
|
||||
"вами адрес электронной почты со ссылкой на эту страницу."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:60
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please save the following link if you want to access your order later. We "
|
||||
#| "also sent you an email containing the link to the address you specified."
|
||||
msgid ""
|
||||
"Please save the following link if you want to access your order later. We "
|
||||
"also sent you an email to the address you specified containing the link."
|
||||
msgstr ""
|
||||
"Пожалуйста, сохраните следующую ссылку, если вы хотите получить доступ к "
|
||||
"вашему заказу позже. Мы также отправили вам электронное письмо со ссылкой на "
|
||||
"указанный вами адрес."
|
||||
"Пожалуйста, сохраните ссылку на эту страницу, если вам потребуется доступ к "
|
||||
"заказу позже. Мы также отправили письмо на указанный вами адрес электронной "
|
||||
"почты со ссылкой на эту страницу."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:75
|
||||
#: pretix/presale/templates/pretixpresale/event/position.html:18
|
||||
@@ -36551,14 +36580,11 @@ msgstr "Включить вебхук"
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:36
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher_form.html:9
|
||||
msgid "Voucher redemption"
|
||||
msgstr "Использование ваучера"
|
||||
msgstr "Активация промокода"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:20
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "This voucher is not valid for this event date."
|
||||
msgid "This voucher is valid only for the following specific date and time."
|
||||
msgstr "Этот ваучер не действителен на эту дату мероприятия."
|
||||
msgstr "Этот промокод действителен только на указанную дату и время."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:43
|
||||
msgid ""
|
||||
@@ -36577,8 +36603,8 @@ msgid ""
|
||||
"You entered a voucher code that allows you to buy one of the following "
|
||||
"products at the specified price:"
|
||||
msgstr ""
|
||||
"Вы ввели код ваучера, который позволяет вам купить один из следующих "
|
||||
"продуктов по указанной цене:"
|
||||
"Вы ввели промокод, который позволяет вам купить один из следующих продуктов "
|
||||
"по указанной цене:"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:112
|
||||
#, python-format
|
||||
|
||||
@@ -27,7 +27,7 @@ from django.urls import NoReverseMatch
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.html import conditional_escape
|
||||
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, mainreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute, mainreverse
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -49,7 +49,7 @@ class EventURLNode(URLNode):
|
||||
url = ''
|
||||
try:
|
||||
if self.absolute:
|
||||
url = build_absolute_uri(event, view_name, kwargs=kwargs)
|
||||
url = eventreverse_absolute(event, view_name, kwargs=kwargs)
|
||||
elif self.event is False:
|
||||
url = mainreverse(view_name, kwargs)
|
||||
else:
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
import warnings
|
||||
from urllib.parse import urljoin, urlsplit
|
||||
|
||||
from django.conf import settings
|
||||
@@ -190,6 +191,15 @@ def eventreverse(obj, name, kwargs=None):
|
||||
|
||||
|
||||
def build_absolute_uri(obj, urlname, kwargs=None):
|
||||
warnings.warn(
|
||||
'Usage of build_absolute_uri is confusing since there are many functions with that name. '
|
||||
'Replace this usage with eventreverse_absolute',
|
||||
DeprecationWarning
|
||||
)
|
||||
return eventreverse_absolute(obj, urlname, kwargs)
|
||||
|
||||
|
||||
def eventreverse_absolute(obj, urlname, kwargs=None):
|
||||
"""
|
||||
Works similar to ``eventreverse`` but always returns an absolute URL.
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ from pretix.base.timeframes import (
|
||||
from pretix.control.forms.widgets import Select2
|
||||
from pretix.helpers.filenames import safe_for_filename
|
||||
from pretix.helpers.iter import chunked_iterable
|
||||
from pretix.helpers.reportlab import FontFallbackParagraph
|
||||
from pretix.helpers.reportlab import PlainTextParagraph
|
||||
from pretix.helpers.templatetags.jsonfield import JSONExtract
|
||||
from pretix.plugins.reports.exporters import ReportlabExportMixin
|
||||
|
||||
@@ -343,7 +343,7 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
]
|
||||
|
||||
story = [
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
cl.name,
|
||||
headlinestyle
|
||||
),
|
||||
@@ -351,7 +351,7 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
if cl.subevent:
|
||||
story += [
|
||||
Spacer(1, 3 * mm),
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
'{} ({} {})'.format(
|
||||
cl.subevent.name,
|
||||
cl.subevent.get_date_range_display(),
|
||||
@@ -381,10 +381,10 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
headrowstyle.fontName = 'OpenSansBd'
|
||||
for q in questions:
|
||||
txt = str(q.question)
|
||||
p = FontFallbackParagraph(txt, headrowstyle)
|
||||
p = PlainTextParagraph(txt, headrowstyle)
|
||||
while p.wrap(colwidths[len(tdata[0])], 5000)[1] > 30 * mm:
|
||||
txt = txt[:len(txt) - 50] + "..."
|
||||
p = FontFallbackParagraph(txt, headrowstyle)
|
||||
p = PlainTextParagraph(txt, headrowstyle)
|
||||
tdata[0].append(p)
|
||||
|
||||
qs = self._get_queryset(cl, form_data)
|
||||
@@ -431,8 +431,8 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
CBFlowable(bool(op.last_checked_in)) if not op.blocked else '—',
|
||||
'✘' if op.order.status != Order.STATUS_PAID else '✔',
|
||||
op.order.code,
|
||||
FontFallbackParagraph(name, self.get_style()),
|
||||
FontFallbackParagraph(bleach.clean(str(item), tags={'br'}).strip().replace('<br>', '<br/>'), self.get_style()),
|
||||
PlainTextParagraph(name, self.get_style()),
|
||||
PlainTextParagraph(bleach.clean(str(item), tags={'br'}).strip().replace('<br>', '<br/>'), self.get_style()),
|
||||
]
|
||||
acache = {}
|
||||
if op.addon_to:
|
||||
@@ -443,10 +443,10 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter):
|
||||
for q in questions:
|
||||
txt = acache.get(q.pk, '')
|
||||
txt = bleach.clean(txt, tags={'br'}).strip().replace('<br>', '<br/>')
|
||||
p = FontFallbackParagraph(txt, self.get_style())
|
||||
p = PlainTextParagraph(txt, self.get_style())
|
||||
while p.wrap(colwidths[len(row)], 5000)[1] > 50 * mm:
|
||||
txt = txt[:len(txt) - 50] + "..."
|
||||
p = FontFallbackParagraph(txt, self.get_style())
|
||||
p = PlainTextParagraph(txt, self.get_style())
|
||||
row.append(p)
|
||||
if op.order.status != Order.STATUS_PAID:
|
||||
tstyledata += [
|
||||
|
||||
@@ -58,7 +58,7 @@ from pretix.base.forms import SecretKeySettingsField
|
||||
from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
|
||||
from pretix.base.payment import BasePaymentProvider, PaymentException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.plugins.paypal.api import Api
|
||||
from pretix.plugins.paypal.models import ReferencedPayPalObject
|
||||
|
||||
@@ -268,8 +268,8 @@ class Paypal(BasePaymentProvider):
|
||||
"payment_method": "paypal",
|
||||
},
|
||||
"redirect_urls": {
|
||||
"return_url": build_absolute_uri(request.event, 'plugins:paypal:return', kwargs=kwargs),
|
||||
"cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort', kwargs=kwargs),
|
||||
"return_url": eventreverse_absolute(request.event, 'plugins:paypal:return', kwargs=kwargs),
|
||||
"cancel_url": eventreverse_absolute(request.event, 'plugins:paypal:abort', kwargs=kwargs),
|
||||
},
|
||||
"transactions": [
|
||||
{
|
||||
@@ -351,7 +351,7 @@ class Paypal(BasePaymentProvider):
|
||||
if request.session.get('iframe_session', False):
|
||||
signer = signing.Signer(salt='safe-redirect')
|
||||
return (
|
||||
build_absolute_uri(request.event, 'plugins:paypal:redirect') + '?url=' +
|
||||
eventreverse_absolute(request.event, 'plugins:paypal:redirect') + '?url=' +
|
||||
urllib.parse.quote(signer.sign(link.href))
|
||||
)
|
||||
else:
|
||||
@@ -613,8 +613,8 @@ class Paypal(BasePaymentProvider):
|
||||
"payment_method": "paypal",
|
||||
},
|
||||
"redirect_urls": {
|
||||
"return_url": build_absolute_uri(request.event, 'plugins:paypal:return'),
|
||||
"cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'),
|
||||
"return_url": eventreverse_absolute(request.event, 'plugins:paypal:return'),
|
||||
"cancel_url": eventreverse_absolute(request.event, 'plugins:paypal:abort'),
|
||||
},
|
||||
"transactions": [
|
||||
{
|
||||
|
||||
@@ -56,8 +56,8 @@ from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
|
||||
from pretix.base.payment import BasePaymentProvider, PaymentException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.plugins.paypal2.client.core.environment import (
|
||||
LiveEnvironment, SandboxEnvironment,
|
||||
)
|
||||
@@ -264,7 +264,7 @@ class PaypalSettingsHolder(BasePaymentProvider):
|
||||
settings_content = "<div class='alert alert-info'>%s<br /><code>%s</code></div>" % (
|
||||
_('Please configure a PayPal Webhook to the following endpoint in order to automatically cancel orders '
|
||||
'when payments are refunded externally.'),
|
||||
build_global_uri('plugins:paypal2:webhook')
|
||||
mainreverse_absolute('plugins:paypal2:webhook')
|
||||
)
|
||||
|
||||
if self.event.currency not in SUPPORTED_CURRENCIES:
|
||||
@@ -321,7 +321,7 @@ class PaypalSettingsHolder(BasePaymentProvider):
|
||||
],
|
||||
"partner_config_override": {
|
||||
"partner_logo_url": urllib.parse.urljoin(settings.SITE_URL, static('pretixbase/img/pretix-logo.svg')),
|
||||
"return_url": build_global_uri('plugins:paypal2:isu.return', kwargs={
|
||||
"return_url": mainreverse_absolute('plugins:paypal2:isu.return', kwargs={
|
||||
'organizer': self.event.organizer.slug,
|
||||
'event': self.event.slug,
|
||||
})
|
||||
@@ -585,8 +585,8 @@ class PaypalMethod(BasePaymentProvider):
|
||||
'locale': request.LANGUAGE_CODE.split('-')[0],
|
||||
'shipping_preference': 'NO_SHIPPING', # 'SET_PROVIDED_ADDRESS', # Do not set on non-ship order?
|
||||
'user_action': 'CONTINUE',
|
||||
'return_url': build_absolute_uri(request.event, 'plugins:paypal2:return', kwargs=kwargs),
|
||||
'cancel_url': build_absolute_uri(request.event, 'plugins:paypal2:abort', kwargs=kwargs),
|
||||
'return_url': eventreverse_absolute(request.event, 'plugins:paypal2:return', kwargs=kwargs),
|
||||
'cancel_url': eventreverse_absolute(request.event, 'plugins:paypal2:abort', kwargs=kwargs),
|
||||
},
|
||||
})
|
||||
response = self.client.execute(paymentreq)
|
||||
|
||||
@@ -36,7 +36,7 @@ from reportlab.lib import colors, pagesizes
|
||||
from reportlab.lib.enums import TA_CENTER, TA_RIGHT
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.platypus import (
|
||||
KeepTogether, PageTemplate, Paragraph, Spacer, Table, TableStyle,
|
||||
KeepTogether, PageTemplate, Spacer, Table, TableStyle,
|
||||
)
|
||||
|
||||
from pretix.base.exporter import BaseExporter
|
||||
@@ -49,7 +49,7 @@ from pretix.base.timeframes import (
|
||||
resolve_timeframe_to_datetime_start_inclusive_end_exclusive,
|
||||
)
|
||||
from pretix.control.forms.filter import get_all_payment_providers
|
||||
from pretix.helpers.reportlab import FontFallbackParagraph
|
||||
from pretix.helpers.reportlab import PlainTextParagraph
|
||||
from pretix.plugins.reports.exporters import ReportlabExportMixin
|
||||
|
||||
|
||||
@@ -270,18 +270,18 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
def _transaction_group_header_label(self):
|
||||
return _("Event") + " / " + _("Product")
|
||||
|
||||
def _transaction_group_label(self, form_data, r):
|
||||
def _transaction_group(self, form_data, r):
|
||||
if not self.is_multievent and not form_data.get("split_subevents"):
|
||||
return None
|
||||
return None, None
|
||||
if r.get("subevent_id"):
|
||||
return "{} - {} ({}) [{}]".format(
|
||||
r["order__event__name"],
|
||||
r["subevent__name"],
|
||||
date_format(r["subevent__date_from"]),
|
||||
r["order__event__slug"]
|
||||
)
|
||||
), f"subevent-{r['subevent_id']}"
|
||||
else:
|
||||
return "{} [{}]".format(r["order__event__name"], r["order__event__slug"])
|
||||
return "{} [{}]".format(r["order__event__name"], r["order__event__slug"]), f"event-{r['order__event__slug']}"
|
||||
|
||||
def _transaction_row_label(self, r):
|
||||
if r["item_id"]:
|
||||
@@ -311,13 +311,13 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
|
||||
tdata = [
|
||||
[
|
||||
FontFallbackParagraph(self._transaction_group_header_label(), tstyle_bold),
|
||||
FontFallbackParagraph(_("Price"), tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Tax rate"), tstyle_bold_right),
|
||||
FontFallbackParagraph("#", tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Net total"), tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Tax total"), tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Gross total"), tstyle_bold_right),
|
||||
PlainTextParagraph(self._transaction_group_header_label(), tstyle_bold),
|
||||
PlainTextParagraph(_("Price"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Tax rate"), tstyle_bold_right),
|
||||
PlainTextParagraph("#", tstyle_bold_right),
|
||||
PlainTextParagraph(_("Net total"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Tax total"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Gross total"), tstyle_bold_right),
|
||||
]
|
||||
]
|
||||
|
||||
@@ -343,17 +343,17 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
last_group = None
|
||||
last_group_head_idx = 0
|
||||
for r in qs:
|
||||
e = self._transaction_group_label(form_data, r)
|
||||
group_label, group_id = self._transaction_group(form_data, r)
|
||||
|
||||
if e != last_group:
|
||||
if last_group_head_idx > 0 and e is not None:
|
||||
tdata[last_group_head_idx][4] = Paragraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][5] = Paragraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][6] = Paragraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
|
||||
if group_id != last_group:
|
||||
if last_group_head_idx > 0 and group_id is not None:
|
||||
tdata[last_group_head_idx][4] = PlainTextParagraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][5] = PlainTextParagraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][6] = PlainTextParagraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(
|
||||
e,
|
||||
PlainTextParagraph(
|
||||
group_label,
|
||||
tstyle_bold,
|
||||
),
|
||||
"",
|
||||
@@ -367,7 +367,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
tstyledata.append(
|
||||
("SPAN", (0, len(tdata) - 1), (3, len(tdata) - 1)),
|
||||
)
|
||||
last_group = e
|
||||
last_group = group_id
|
||||
last_group_head_idx = len(tdata) - 1
|
||||
sum_price_by_group = Decimal("0.00")
|
||||
sum_tax_by_group = Decimal("0.00")
|
||||
@@ -375,20 +375,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
text = self._transaction_row_label(r)
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(text, tstyle),
|
||||
Paragraph(
|
||||
PlainTextParagraph(text, tstyle),
|
||||
PlainTextParagraph(
|
||||
money_filter(r["price"], currency)
|
||||
if "price" in r and r["price"] is not None
|
||||
else "",
|
||||
tstyle_right,
|
||||
),
|
||||
Paragraph(localize(r["tax_rate"].normalize()) + " %", tstyle_right),
|
||||
Paragraph(str(r["sum_cont"]), tstyle_right),
|
||||
Paragraph(
|
||||
PlainTextParagraph(localize(r["tax_rate"].normalize()) + " %", tstyle_right),
|
||||
PlainTextParagraph(str(r["sum_cont"]), tstyle_right),
|
||||
PlainTextParagraph(
|
||||
money_filter(r["sum_price"] - r["sum_tax"], currency), tstyle_right
|
||||
),
|
||||
Paragraph(money_filter(r["sum_tax"], currency), tstyle_right),
|
||||
Paragraph(money_filter(r["sum_price"], currency), tstyle_right),
|
||||
PlainTextParagraph(money_filter(r["sum_tax"], currency), tstyle_right),
|
||||
PlainTextParagraph(money_filter(r["sum_price"], currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
sum_cnt_by_tax_rate[r["tax_rate"]] += r["sum_cont"]
|
||||
@@ -398,19 +398,19 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
sum_tax_by_group += r["sum_tax"]
|
||||
|
||||
if last_group_head_idx > 0 and last_group is not None:
|
||||
tdata[last_group_head_idx][4] = Paragraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][5] = Paragraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][6] = Paragraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][4] = PlainTextParagraph(money_filter(sum_price_by_group - sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][5] = PlainTextParagraph(money_filter(sum_tax_by_group, currency), tstyle_bold_right),
|
||||
tdata[last_group_head_idx][6] = PlainTextParagraph(money_filter(sum_price_by_group, currency), tstyle_bold_right),
|
||||
|
||||
if len(sum_tax_by_tax_rate) > 1:
|
||||
for tax_rate in sorted(sum_tax_by_tax_rate.keys(), reverse=True):
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Sum"), tstyle),
|
||||
Paragraph("", tstyle_right),
|
||||
Paragraph(localize(tax_rate.normalize()) + " %", tstyle_right),
|
||||
Paragraph("", tstyle_right),
|
||||
Paragraph(
|
||||
PlainTextParagraph(_("Sum"), tstyle),
|
||||
PlainTextParagraph("", tstyle_right),
|
||||
PlainTextParagraph(localize(tax_rate.normalize()) + " %", tstyle_right),
|
||||
PlainTextParagraph("", tstyle_right),
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
sum_price_by_tax_rate[tax_rate]
|
||||
- sum_tax_by_tax_rate[tax_rate],
|
||||
@@ -418,10 +418,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
),
|
||||
tstyle_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(sum_tax_by_tax_rate[tax_rate], currency), tstyle_right
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(sum_price_by_tax_rate[tax_rate], currency),
|
||||
tstyle_right,
|
||||
),
|
||||
@@ -439,11 +439,11 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Sum"), tstyle_bold),
|
||||
Paragraph("", tstyle_right),
|
||||
Paragraph("", tstyle_right),
|
||||
Paragraph("", tstyle_bold_right),
|
||||
Paragraph(
|
||||
PlainTextParagraph(_("Sum"), tstyle_bold),
|
||||
PlainTextParagraph("", tstyle_right),
|
||||
PlainTextParagraph("", tstyle_right),
|
||||
PlainTextParagraph("", tstyle_bold_right),
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
sum(sum_price_by_tax_rate.values())
|
||||
- sum(sum_tax_by_tax_rate.values()),
|
||||
@@ -451,11 +451,11 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
),
|
||||
tstyle_bold_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(sum(sum_tax_by_tax_rate.values()), currency),
|
||||
tstyle_bold_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(sum(sum_price_by_tax_rate.values()), currency),
|
||||
tstyle_bold_right,
|
||||
),
|
||||
@@ -493,10 +493,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
|
||||
tdata = [
|
||||
[
|
||||
FontFallbackParagraph(_("Payment method"), tstyle_bold),
|
||||
FontFallbackParagraph(_("Payments"), tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Refunds"), tstyle_bold_right),
|
||||
FontFallbackParagraph(_("Total"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Payment method"), tstyle_bold),
|
||||
PlainTextParagraph(_("Payments"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Refunds"), tstyle_bold_right),
|
||||
PlainTextParagraph(_("Total"), tstyle_bold_right),
|
||||
]
|
||||
]
|
||||
|
||||
@@ -537,20 +537,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
for p in providers:
|
||||
tdata.append(
|
||||
[
|
||||
Paragraph(provider_names.get(p, p), tstyle),
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(provider_names.get(p, p), tstyle),
|
||||
PlainTextParagraph(
|
||||
money_filter(payments_by_provider[p], currency)
|
||||
if p in payments_by_provider
|
||||
else "",
|
||||
tstyle_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(refunds_by_provider[p], currency)
|
||||
if p in refunds_by_provider
|
||||
else "",
|
||||
tstyle_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
payments_by_provider.get(p, Decimal("0.00"))
|
||||
- refunds_by_provider.get(p, Decimal("0.00")),
|
||||
@@ -563,20 +563,20 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Sum"), tstyle_bold),
|
||||
Paragraph(
|
||||
PlainTextParagraph(_("Sum"), tstyle_bold),
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
sum(payments_by_provider.values(), Decimal("0.00")), currency
|
||||
),
|
||||
tstyle_bold_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
sum(refunds_by_provider.values(), Decimal("0.00")), currency
|
||||
),
|
||||
tstyle_bold_right,
|
||||
),
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
money_filter(
|
||||
sum(payments_by_provider.values(), Decimal("0.00"))
|
||||
- sum(refunds_by_provider.values(), Decimal("0.00")),
|
||||
@@ -641,7 +641,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
open_before = tx_before - p_before + r_before
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(
|
||||
PlainTextParagraph(
|
||||
_("Pending payments at {datetime}").format(
|
||||
datetime=date_format(
|
||||
(df_start - datetime.timedelta.resolution).astimezone(
|
||||
@@ -653,7 +653,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
tstyle,
|
||||
),
|
||||
"",
|
||||
Paragraph(money_filter(open_before, currency), tstyle_right),
|
||||
PlainTextParagraph(money_filter(open_before, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
else:
|
||||
@@ -670,30 +670,30 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
] or Decimal("0.00")
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Orders"), tstyle),
|
||||
Paragraph("+", tstyle_center),
|
||||
Paragraph(money_filter(tx_during, currency), tstyle_right),
|
||||
PlainTextParagraph(_("Orders"), tstyle),
|
||||
PlainTextParagraph("+", tstyle_center),
|
||||
PlainTextParagraph(money_filter(tx_during, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Payments"), tstyle),
|
||||
Paragraph("-", tstyle_center),
|
||||
Paragraph(money_filter(p_during, currency), tstyle_right),
|
||||
PlainTextParagraph(_("Payments"), tstyle),
|
||||
PlainTextParagraph("-", tstyle_center),
|
||||
PlainTextParagraph(money_filter(p_during, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Refunds"), tstyle),
|
||||
Paragraph("+", tstyle_center),
|
||||
Paragraph(money_filter(r_during, currency), tstyle_right),
|
||||
PlainTextParagraph(_("Refunds"), tstyle),
|
||||
PlainTextParagraph("+", tstyle_center),
|
||||
PlainTextParagraph(money_filter(r_during, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
|
||||
open_after = open_before + tx_during - p_during + r_during
|
||||
tdata.append(
|
||||
[
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
_("Pending payments at {datetime}").format(
|
||||
datetime=date_format(
|
||||
((df_end or now()) - datetime.timedelta.resolution).astimezone(
|
||||
@@ -704,8 +704,8 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
),
|
||||
tstyle_bold,
|
||||
),
|
||||
Paragraph("=", tstyle_center),
|
||||
Paragraph(money_filter(open_after, currency), tstyle_bold_right),
|
||||
PlainTextParagraph("=", tstyle_center),
|
||||
PlainTextParagraph(money_filter(open_after, currency), tstyle_bold_right),
|
||||
]
|
||||
)
|
||||
tstyledata += [
|
||||
@@ -752,7 +752,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
)
|
||||
tdata.append(
|
||||
[
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
_("Total gift card value at {datetime}").format(
|
||||
datetime=date_format(
|
||||
(df_start - datetime.timedelta.resolution).astimezone(
|
||||
@@ -763,7 +763,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
),
|
||||
tstyle,
|
||||
),
|
||||
Paragraph(money_filter(tx_before, currency), tstyle_right),
|
||||
PlainTextParagraph(money_filter(tx_before, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
else:
|
||||
@@ -774,8 +774,8 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
] or Decimal("0.00")
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Gift card transactions (credit)"), tstyle),
|
||||
Paragraph(money_filter(tx_during_pos, currency), tstyle_right),
|
||||
PlainTextParagraph(_("Gift card transactions (credit)"), tstyle),
|
||||
PlainTextParagraph(money_filter(tx_during_pos, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -784,15 +784,15 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
] or Decimal("0.00")
|
||||
tdata.append(
|
||||
[
|
||||
FontFallbackParagraph(_("Gift card transactions (debit)"), tstyle),
|
||||
Paragraph(money_filter(tx_during_neg, currency), tstyle_right),
|
||||
PlainTextParagraph(_("Gift card transactions (debit)"), tstyle),
|
||||
PlainTextParagraph(money_filter(tx_during_neg, currency), tstyle_right),
|
||||
]
|
||||
)
|
||||
|
||||
open_after = tx_before + tx_during_pos + tx_during_neg
|
||||
tdata.append(
|
||||
[
|
||||
Paragraph(
|
||||
PlainTextParagraph(
|
||||
_("Total gift card value at {datetime}").format(
|
||||
datetime=date_format(
|
||||
((df_end or now()) - datetime.timedelta.resolution).astimezone(
|
||||
@@ -803,7 +803,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
),
|
||||
tstyle_bold,
|
||||
),
|
||||
Paragraph(money_filter(open_after, currency), tstyle_bold_right),
|
||||
PlainTextParagraph(money_filter(open_after, currency), tstyle_bold_right),
|
||||
]
|
||||
)
|
||||
tstyledata += [
|
||||
@@ -854,10 +854,10 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
style_small.leading = 10
|
||||
|
||||
story = [
|
||||
FontFallbackParagraph(self.verbose_name, style_h1),
|
||||
PlainTextParagraph(self.verbose_name, style_h1),
|
||||
Spacer(0, 3 * mm),
|
||||
FontFallbackParagraph(
|
||||
"<br />".join(escape(f) for f in self.describe_filters(form_data)),
|
||||
PlainTextParagraph(
|
||||
"\n".join(escape(f) for f in self.describe_filters(form_data)),
|
||||
style_small,
|
||||
),
|
||||
]
|
||||
@@ -870,7 +870,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
if s:
|
||||
story += [
|
||||
Spacer(0, 3 * mm),
|
||||
FontFallbackParagraph(_("Orders") + c_head, style_h2),
|
||||
PlainTextParagraph(_("Orders") + c_head, style_h2),
|
||||
Spacer(0, 3 * mm),
|
||||
*s
|
||||
]
|
||||
@@ -881,7 +881,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
if s:
|
||||
story += [
|
||||
Spacer(0, 8 * mm),
|
||||
FontFallbackParagraph(_("Payments") + c_head, style_h2),
|
||||
PlainTextParagraph(_("Payments") + c_head, style_h2),
|
||||
Spacer(0, 3 * mm),
|
||||
*s
|
||||
]
|
||||
@@ -894,7 +894,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
Spacer(0, 8 * mm),
|
||||
KeepTogether(
|
||||
[
|
||||
FontFallbackParagraph(_("Open items") + c_head, style_h2),
|
||||
PlainTextParagraph(_("Open items") + c_head, style_h2),
|
||||
Spacer(0, 3 * mm),
|
||||
*s
|
||||
]
|
||||
@@ -912,7 +912,7 @@ class ReportExporter(ReportlabExportMixin, BaseExporter):
|
||||
Spacer(0, 8 * mm),
|
||||
KeepTogether(
|
||||
[
|
||||
FontFallbackParagraph(_("Gift cards") + c_head, style_h2),
|
||||
PlainTextParagraph(_("Gift cards") + c_head, style_h2),
|
||||
Spacer(0, 3 * mm),
|
||||
*s,
|
||||
]
|
||||
|
||||
@@ -70,7 +70,7 @@ from pretix.base.timeframes import (
|
||||
)
|
||||
from pretix.control.forms.filter import OverviewFilterForm
|
||||
from pretix.helpers.reportlab import (
|
||||
FontFallbackParagraph, register_ttf_font_if_new,
|
||||
PlainTextParagraph, register_ttf_font_if_new,
|
||||
)
|
||||
from pretix.presale.style import get_fonts
|
||||
|
||||
@@ -282,7 +282,7 @@ class OverviewReport(Report):
|
||||
headlinestyle.fontSize = 15
|
||||
headlinestyle.fontName = 'OpenSansBd'
|
||||
story = [
|
||||
FontFallbackParagraph(_('Orders by product') + ' ' + (_('(excl. taxes)') if net else _('(incl. taxes)')), headlinestyle),
|
||||
PlainTextParagraph(_('Orders by product') + ' ' + (_('(excl. taxes)') if net else _('(incl. taxes)')), headlinestyle),
|
||||
Spacer(1, 5 * mm)
|
||||
]
|
||||
return story
|
||||
@@ -292,7 +292,7 @@ class OverviewReport(Report):
|
||||
if form_data.get('date_axis') and form_data.get('date_range'):
|
||||
d_start, d_end = resolve_timeframe_to_dates_inclusive(now(), form_data['date_range'], self.timezone)
|
||||
story += [
|
||||
FontFallbackParagraph(_('{axis} between {start} and {end}').format(
|
||||
PlainTextParagraph(_('{axis} between {start} and {end}').format(
|
||||
axis=dict(OverviewFilterForm(event=self.event).fields['date_axis'].choices)[form_data.get('date_axis')],
|
||||
start=date_format(d_start, 'SHORT_DATE_FORMAT') if d_start else '–',
|
||||
end=date_format(d_end, 'SHORT_DATE_FORMAT') if d_end else '–',
|
||||
@@ -305,13 +305,13 @@ class OverviewReport(Report):
|
||||
subevent = self.event.subevents.get(pk=self.form_data.get('subevent'))
|
||||
except SubEvent.DoesNotExist:
|
||||
subevent = self.form_data.get('subevent')
|
||||
story.append(FontFallbackParagraph(pgettext('subevent', 'Date: {}').format(subevent), self.get_style()))
|
||||
story.append(PlainTextParagraph(pgettext('subevent', 'Date: {}').format(subevent), self.get_style()))
|
||||
story.append(Spacer(1, 5 * mm))
|
||||
|
||||
if form_data.get('subevent_date_range'):
|
||||
d_start, d_end = resolve_timeframe_to_datetime_start_inclusive_end_exclusive(now(), form_data['subevent_date_range'], self.timezone)
|
||||
story += [
|
||||
FontFallbackParagraph(_('{axis} between {start} and {end}').format(
|
||||
PlainTextParagraph(_('{axis} between {start} and {end}').format(
|
||||
axis=_('Event date'),
|
||||
start=date_format(d_start, 'SHORT_DATE_FORMAT') if d_start else '–',
|
||||
end=date_format(d_end - timedelta(hours=1), 'SHORT_DATE_FORMAT') if d_end else '–',
|
||||
@@ -384,13 +384,13 @@ class OverviewReport(Report):
|
||||
tdata = [
|
||||
[
|
||||
_('Product'),
|
||||
FontFallbackParagraph(_('Canceled'), tstyle_th),
|
||||
PlainTextParagraph(_('Canceled'), tstyle_th),
|
||||
'',
|
||||
FontFallbackParagraph(_('Expired'), tstyle_th),
|
||||
PlainTextParagraph(_('Expired'), tstyle_th),
|
||||
'',
|
||||
FontFallbackParagraph(_('Approval pending'), tstyle_th),
|
||||
PlainTextParagraph(_('Approval pending'), tstyle_th),
|
||||
'',
|
||||
FontFallbackParagraph(_('Purchased'), tstyle_th),
|
||||
PlainTextParagraph(_('Purchased'), tstyle_th),
|
||||
'', '', '', '', ''
|
||||
],
|
||||
[
|
||||
@@ -421,14 +421,14 @@ class OverviewReport(Report):
|
||||
for tup in items_by_category:
|
||||
if tup[0]:
|
||||
tdata.append([
|
||||
FontFallbackParagraph(str(tup[0]), tstyle_bold)
|
||||
PlainTextParagraph(str(tup[0]), tstyle_bold)
|
||||
])
|
||||
for l, s in states:
|
||||
tdata[-1].append(str(tup[0].num[l][0]))
|
||||
tdata[-1].append(floatformat(tup[0].num[l][2 if net else 1], places))
|
||||
for item in tup[1]:
|
||||
tdata.append([
|
||||
FontFallbackParagraph(str(item), tstyle)
|
||||
PlainTextParagraph(str(item), tstyle)
|
||||
])
|
||||
for l, s in states:
|
||||
tdata[-1].append(str(item.num[l][0]))
|
||||
@@ -436,7 +436,7 @@ class OverviewReport(Report):
|
||||
if item.has_variations:
|
||||
for var in item.all_variations:
|
||||
tdata.append([
|
||||
FontFallbackParagraph(" " + str(var), tstyle)
|
||||
PlainTextParagraph(" " + str(var), tstyle)
|
||||
])
|
||||
for l, s in states:
|
||||
tdata[-1].append(str(var.num[l][0]))
|
||||
@@ -568,7 +568,7 @@ class OrderTaxListReportPDF(Report):
|
||||
tstyledata.append(('SPAN', (5 + 2 * i, 0), (6 + 2 * i, 0)))
|
||||
|
||||
story = [
|
||||
FontFallbackParagraph(_('Orders by tax rate ({currency})').format(currency=self.event.currency), headlinestyle),
|
||||
PlainTextParagraph(_('Orders by tax rate ({currency})').format(currency=self.event.currency), headlinestyle),
|
||||
Spacer(1, 5 * mm)
|
||||
]
|
||||
tdata = [
|
||||
|
||||
@@ -75,8 +75,8 @@ from pretix.base.settings import SettingsSandbox
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
from pretix.helpers.http import get_client_ip
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.plugins.stripe.forms import StripeKeyValidator
|
||||
from pretix.plugins.stripe.models import (
|
||||
ReferencedStripeObject, RegisteredApplePayDomain,
|
||||
@@ -197,7 +197,7 @@ class StripeSettingsHolder(BasePaymentProvider):
|
||||
).format(
|
||||
self.settings.connect_client_id,
|
||||
request.session['payment_stripe_oauth_token'],
|
||||
urllib.parse.quote(build_global_uri('plugins:stripe:oauth.return')),
|
||||
urllib.parse.quote(mainreverse_absolute('plugins:stripe:oauth.return')),
|
||||
)
|
||||
|
||||
def settings_content_render(self, request):
|
||||
@@ -229,7 +229,7 @@ class StripeSettingsHolder(BasePaymentProvider):
|
||||
_('Please configure a <a href="https://dashboard.stripe.com/account/webhooks">Stripe Webhook</a> to '
|
||||
'the following endpoint in order to automatically cancel orders when charges are refunded externally '
|
||||
'and to process asynchronous payment methods like SOFORT.'),
|
||||
build_global_uri('plugins:stripe:webhook')
|
||||
mainreverse_absolute('plugins:stripe:webhook')
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -746,7 +746,7 @@ class StripeMethod(BasePaymentProvider):
|
||||
def redirect(self, request, url):
|
||||
if request.session.get('iframe_session', False):
|
||||
return (
|
||||
build_absolute_uri(request.event, 'plugins:stripe:redirect') +
|
||||
eventreverse_absolute(request.event, 'plugins:stripe:redirect') +
|
||||
'?data=' + signing.dumps({
|
||||
'url': url,
|
||||
'session': {
|
||||
@@ -941,7 +941,7 @@ class StripeMethod(BasePaymentProvider):
|
||||
},
|
||||
# TODO: Is this sufficient?
|
||||
idempotency_key=str(self.event.id) + payment.order.code + idempotency_key_seed,
|
||||
return_url=build_absolute_uri(self.event, 'plugins:stripe:sca.return', kwargs={
|
||||
return_url=eventreverse_absolute(self.event, 'plugins:stripe:sca.return', kwargs={
|
||||
'order': payment.order.code,
|
||||
'payment': payment.pk,
|
||||
'hash': payment.order.tagged_secret('plugins:stripe'),
|
||||
@@ -1047,13 +1047,13 @@ class StripeMethod(BasePaymentProvider):
|
||||
raise PaymentException(_('Stripe reported an error: %s') % intent.last_payment_error.message)
|
||||
|
||||
def _redirect_to_sca(self, request, payment):
|
||||
url = build_absolute_uri(self.event, 'plugins:stripe:sca', kwargs={
|
||||
url = eventreverse_absolute(self.event, 'plugins:stripe:sca', kwargs={
|
||||
'order': payment.order.code,
|
||||
'payment': payment.pk,
|
||||
'hash': payment.order.tagged_secret('plugins:stripe'),
|
||||
})
|
||||
if not self.redirect_in_widget_allowed and request.session.get('iframe_session', False):
|
||||
return build_absolute_uri(self.event, 'plugins:stripe:redirect') + '?data=' + signing.dumps({
|
||||
return eventreverse_absolute(self.event, 'plugins:stripe:redirect') + '?data=' + signing.dumps({
|
||||
'url': url,
|
||||
'session': {},
|
||||
}, salt='safe-redirect')
|
||||
@@ -1068,7 +1068,7 @@ class StripeMethod(BasePaymentProvider):
|
||||
|
||||
intent = stripe.PaymentIntent.confirm(
|
||||
payment_info['id'],
|
||||
return_url=build_absolute_uri(self.event, 'plugins:stripe:sca.return', kwargs={
|
||||
return_url=eventreverse_absolute(self.event, 'plugins:stripe:sca.return', kwargs={
|
||||
'order': payment.order.code,
|
||||
'payment': payment.pk,
|
||||
'hash': payment.order.tagged_secret('plugins:stripe'),
|
||||
|
||||
@@ -64,7 +64,7 @@ from pretix.control.views.event import DecoupleMixin
|
||||
from pretix.control.views.organizer import OrganizerDetailViewMixin
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.plugins.stripe.forms import OrganizerStripeSettingsForm
|
||||
from pretix.plugins.stripe.models import ReferencedStripeObject
|
||||
from pretix.plugins.stripe.tasks import (
|
||||
@@ -90,7 +90,7 @@ def redirect_view(request, *args, **kwargs):
|
||||
params = request.GET.copy()
|
||||
params['go'] = '1'
|
||||
r = render(request, 'pretixplugins/stripe/redirect.html', {
|
||||
'url': build_absolute_uri(request.event, 'plugins:stripe:redirect') + '?' + urllib.parse.urlencode(params),
|
||||
'url': eventreverse_absolute(request.event, 'plugins:stripe:redirect') + '?' + urllib.parse.urlencode(params),
|
||||
})
|
||||
r._csp_ignore = True
|
||||
return r
|
||||
|
||||
@@ -51,6 +51,7 @@ from django.http import HttpResponseNotAllowed, JsonResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.utils import translation
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import conditional_escape
|
||||
from django.utils.translation import (
|
||||
get_language, gettext_lazy as _, pgettext_lazy,
|
||||
)
|
||||
@@ -1634,7 +1635,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
||||
meta_info = {
|
||||
'contact_form_data': self.cart_session.get('contact_form_data', {}),
|
||||
'confirm_messages': [
|
||||
str(m) for m in self.confirm_messages.values()
|
||||
conditional_escape(str(m)) for m in self.confirm_messages.values()
|
||||
]
|
||||
}
|
||||
api_meta = {}
|
||||
|
||||
@@ -44,7 +44,7 @@ from pretix.base.forms.questions import (
|
||||
from pretix.base.i18n import get_language_without_region
|
||||
from pretix.base.models import Customer
|
||||
from pretix.helpers.http import get_client_ip
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
|
||||
class TokenGenerator(PasswordResetTokenGenerator):
|
||||
@@ -84,7 +84,7 @@ class AuthenticationForm(forms.Form):
|
||||
self.customer_cache = None
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['password'].help_text = "<a target='_blank' href='{}'>{}</a>".format(
|
||||
build_absolute_uri(False, 'presale:organizer.customer.resetpw', kwargs={
|
||||
eventreverse_absolute(False, 'presale:organizer.customer.resetpw', kwargs={
|
||||
'organizer': request.organizer.slug,
|
||||
}),
|
||||
_('Forgot your password?')
|
||||
|
||||
@@ -32,7 +32,7 @@ from django.utils.translation import gettext as _
|
||||
from pretix.base.email import get_email_context
|
||||
from pretix.base.models import Event
|
||||
from pretix.helpers.format import format_map
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
|
||||
|
||||
def get_public_ical(events):
|
||||
@@ -48,9 +48,9 @@ def get_public_ical(events):
|
||||
event = ev if isinstance(ev, Event) else ev.event
|
||||
tz = event.timezone
|
||||
if isinstance(ev, Event):
|
||||
url = build_absolute_uri(event, 'presale:event.index')
|
||||
url = eventreverse_absolute(event, 'presale:event.index')
|
||||
else:
|
||||
url = build_absolute_uri(event, 'presale:event.index', {
|
||||
url = eventreverse_absolute(event, 'presale:event.index', {
|
||||
'subevent': ev.pk
|
||||
})
|
||||
|
||||
@@ -134,7 +134,7 @@ def get_private_icals(event, positions):
|
||||
program_times = p.item.program_times.all()
|
||||
if program_times:
|
||||
# if program times have been configured, they are preferred for the position's calendar entries
|
||||
url = build_absolute_uri(event, 'presale:event.index')
|
||||
url = eventreverse_absolute(event, 'presale:event.index')
|
||||
for index, pt in enumerate(program_times):
|
||||
summary = _('{event} - {item}').format(event=ev, item=p.item.name)
|
||||
if event.settings.mail_attach_ical_description:
|
||||
@@ -167,11 +167,11 @@ def get_private_icals(event, positions):
|
||||
else:
|
||||
# without program times, the subevent or event times are used for calendar entries, preferring subevents
|
||||
if p.subevent:
|
||||
url = build_absolute_uri(event, 'presale:event.index', {
|
||||
url = eventreverse_absolute(event, 'presale:event.index', {
|
||||
'subevent': p.subevent.pk
|
||||
})
|
||||
else:
|
||||
url = build_absolute_uri(event, 'presale:event.index')
|
||||
url = eventreverse_absolute(event, 'presale:event.index')
|
||||
|
||||
if event.settings.mail_attach_ical_description:
|
||||
ctx = get_email_context(event=event, event_or_subevent=ev)
|
||||
|
||||
@@ -144,7 +144,7 @@ checkout_confirm_messages = EventPluginSignal()
|
||||
This signal is sent out to retrieve short messages that need to be acknowledged by the user before the
|
||||
order can be completed. This is typically used for something like "accept the terms and conditions".
|
||||
Receivers are expected to return a dictionary where the keys are globally unique identifiers for the
|
||||
message and the values can be arbitrary HTML.
|
||||
message and the values can be a SafeString containing arbitrary HTML, or a string that will be HTML-escaped.
|
||||
|
||||
As with all event plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
<div class="checkbox">
|
||||
<label for="input_confirm_{{ key }}">
|
||||
<input type="checkbox" class="checkbox" value="yes" name="confirm_{{ key }}" id="input_confirm_{{ key }}" required>
|
||||
{{ desc|safe }}
|
||||
{{ desc }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
{% load eventsignal %}
|
||||
{% load money %}
|
||||
{% load eventurl %}
|
||||
{% load wrap_in %}
|
||||
{% block title %}{% trans "Registration details" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h2 class="h1">
|
||||
@@ -48,7 +49,7 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
{% blocktrans trimmed with email="<strong>"|add:order.email|add:"</strong>"|safe %}
|
||||
{% blocktrans trimmed with email=order.email|wrap_in:"strong" %}
|
||||
This order is managed for you by {{ email }}. Please contact them for any questions regarding
|
||||
payment, cancellation or changes to this order.
|
||||
{% endblocktrans %}
|
||||
|
||||
@@ -22,4 +22,5 @@
|
||||
<script type="text/javascript" src="{% static "pretixpresale/js/ui/iframe.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/addressform.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/deanonymize_email.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "pretixbase/js/errors.js" %}"></script>
|
||||
{% endcompress %}
|
||||
|
||||
@@ -59,7 +59,7 @@ from pretix.base.timemachine import time_machine_now_assigned_from_request
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import (
|
||||
build_absolute_uri, get_event_domain, get_organizer_domain,
|
||||
eventreverse_absolute, get_event_domain, get_organizer_domain,
|
||||
)
|
||||
from pretix.presale.signals import process_request, process_response
|
||||
|
||||
@@ -283,7 +283,7 @@ def _detect_event(request, require_live=True, require_plugin=None):
|
||||
domain, domainmode = get_event_domain(request.event, fallback=False, return_mode=True)
|
||||
if not domain and request_domain_mode == KnownDomain.MODE_ORG_ALT_DOMAIN:
|
||||
path = request.get_full_path().split("/", 2)[-1]
|
||||
r = redirect_to_url(build_absolute_uri(request.event, "presale:event.index") + path)
|
||||
r = redirect_to_url(eventreverse_absolute(request.event, "presale:event.index") + path)
|
||||
r['Access-Control-Allow-Origin'] = '*'
|
||||
return r
|
||||
elif domain and domain != request.host:
|
||||
|
||||
@@ -56,7 +56,7 @@ from pretix.base.signals import customer_created, customer_signed_in
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.presale.forms.customer import (
|
||||
AuthenticationForm, ChangeInfoForm, ChangePasswordForm, RegistrationForm,
|
||||
ResetPasswordForm, SetPasswordForm, TokenGenerator,
|
||||
@@ -316,8 +316,10 @@ class ResetPasswordView(FormView):
|
||||
customer.log_action('pretix.customer.password.resetrequested', {})
|
||||
ctx = customer.get_email_context()
|
||||
token = TokenGenerator().make_token(customer)
|
||||
ctx['url'] = build_absolute_uri(self.request.organizer,
|
||||
'presale:organizer.customer.recoverpw') + '?id=' + customer.identifier + '&token=' + token
|
||||
ctx['url'] = eventreverse_absolute(
|
||||
self.request.organizer,
|
||||
'presale:organizer.customer.recoverpw'
|
||||
) + '?id=' + customer.identifier + '&token=' + token
|
||||
mail(
|
||||
customer.email,
|
||||
self.request.organizer.settings.mail_subject_customer_reset,
|
||||
@@ -574,7 +576,7 @@ class ChangeInformationView(CustomerAccountBaseMixin, FormView):
|
||||
new_email = form.cleaned_data['email']
|
||||
form.cleaned_data['email'] = form.instance.email = self.initial_email
|
||||
ctx = form.instance.get_email_context()
|
||||
ctx['url'] = build_absolute_uri(
|
||||
ctx['url'] = eventreverse_absolute(
|
||||
self.request.organizer,
|
||||
'presale:organizer.customer.change.confirm'
|
||||
) + '?token=' + dumps({
|
||||
@@ -703,7 +705,7 @@ class SSOLoginView(RedirectBackMixin, View):
|
||||
request.session[f'pretix_customerauth_{self.provider.pk}_nonce'] = nonce
|
||||
request.session[f'pretix_customerauth_{self.provider.pk}_popup_origin'] = popup_origin
|
||||
request.session[f'pretix_customerauth_{self.provider.pk}_cross_domain_requested'] = self.request.GET.get("request_cross_domain_customer_auth") == "true"
|
||||
redirect_uri = build_absolute_uri(self.request.organizer, 'presale:organizer.customer.login.return', kwargs={
|
||||
redirect_uri = eventreverse_absolute(self.request.organizer, 'presale:organizer.customer.login.return', kwargs={
|
||||
'provider': self.provider.pk
|
||||
})
|
||||
|
||||
@@ -777,7 +779,7 @@ class SSOLoginReturnView(RedirectBackMixin, View):
|
||||
),
|
||||
popup_origin,
|
||||
)
|
||||
redirect_uri = build_absolute_uri(
|
||||
redirect_uri = eventreverse_absolute(
|
||||
self.request.organizer, 'presale:organizer.customer.login.return',
|
||||
kwargs={
|
||||
'provider': self.provider.pk
|
||||
|
||||
@@ -46,7 +46,7 @@ from pretix.base.models.customers import (
|
||||
)
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.multidomain.middlewares import CsrfViewMiddleware
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.forms.customer import AuthenticationForm
|
||||
from pretix.presale.utils import customer_login, get_customer_auth_time
|
||||
|
||||
@@ -519,17 +519,17 @@ class ConfigurationView(View):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return JsonResponse({
|
||||
'issuer': build_absolute_uri(request.organizer, 'presale:organizer.index').rstrip('/'),
|
||||
'authorization_endpoint': build_absolute_uri(
|
||||
'issuer': eventreverse_absolute(request.organizer, 'presale:organizer.index').rstrip('/'),
|
||||
'authorization_endpoint': eventreverse_absolute(
|
||||
request.organizer, 'presale:organizer.oauth2.v1.authorize'
|
||||
),
|
||||
'token_endpoint': build_absolute_uri(
|
||||
'token_endpoint': eventreverse_absolute(
|
||||
request.organizer, 'presale:organizer.oauth2.v1.token'
|
||||
),
|
||||
'userinfo_endpoint': build_absolute_uri(
|
||||
'userinfo_endpoint': eventreverse_absolute(
|
||||
request.organizer, 'presale:organizer.oauth2.v1.userinfo'
|
||||
),
|
||||
'jwks_uri': build_absolute_uri(
|
||||
'jwks_uri': eventreverse_absolute(
|
||||
request.organizer, 'presale:organizer.oauth2.v1.jwks'
|
||||
),
|
||||
'scopes_supported': [k for k, v in CustomerSSOClient.SCOPE_CHOICES],
|
||||
|
||||
@@ -89,7 +89,7 @@ from pretix.base.views.mixins import OrderQuestionsViewMixin
|
||||
from pretix.base.views.tasks import AsyncAction
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.helpers.safedownload import check_token
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.presale.forms.checkout import InvoiceAddressForm, QuestionsForm
|
||||
from pretix.presale.forms.order import OrderPositionChangeForm
|
||||
from pretix.presale.signals import question_form_fields_overrides
|
||||
@@ -312,7 +312,7 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin,
|
||||
state__in=[OrderPayment.PAYMENT_STATE_CANCELED, OrderPayment.PAYMENT_STATE_FAILED]
|
||||
).exists() and self.order.status == Order.STATUS_PENDING:
|
||||
ctx['generate_invoice_requires'] = 'payment'
|
||||
ctx['url'] = build_absolute_uri(
|
||||
ctx['url'] = eventreverse_absolute(
|
||||
self.request.event, 'presale:event.order', kwargs={
|
||||
'order': self.order.code,
|
||||
'secret': self.order.secret
|
||||
|
||||
@@ -74,7 +74,7 @@ from pretix.helpers.formats.en.formats import (
|
||||
from pretix.helpers.http import redirect_to_url
|
||||
from pretix.helpers.i18n import parse_date_localized
|
||||
from pretix.helpers.thumb import get_thumbnail
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.presale.forms.organizer import EventListFilterForm
|
||||
from pretix.presale.ical import get_public_ical
|
||||
from pretix.presale.signals import filter_subevents
|
||||
@@ -1380,7 +1380,7 @@ class OrganizerFavicon(View):
|
||||
|
||||
class RedirectToOrganizerIndex(View):
|
||||
def get(self, *args, **kwargs):
|
||||
return redirect_to_url(build_absolute_uri(self.request.organizer, "presale:organizer.index"))
|
||||
return redirect_to_url(eventreverse_absolute(self.request.organizer, "presale:organizer.index"))
|
||||
|
||||
|
||||
class AccessibilityView(OrganizerViewMixin, EventListMixin, TemplateView):
|
||||
|
||||
@@ -65,7 +65,7 @@ from pretix.base.settings import GlobalSettingsObject
|
||||
from pretix.base.templatetags.rich_text import rich_text
|
||||
from pretix.helpers.daterange import daterange
|
||||
from pretix.helpers.thumb import get_thumbnail
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from pretix.presale.forms.organizer import meta_filtersets
|
||||
from pretix.presale.style import get_theme_vars_css
|
||||
from pretix.presale.views.cart import get_or_create_cart_id
|
||||
@@ -303,7 +303,7 @@ def get_picture(event, picture, size=None):
|
||||
logger.exception(f'Failed to create thumbnail of {picture.name}')
|
||||
if not thumb:
|
||||
thumb = default_storage.url(picture.name)
|
||||
return urljoin(build_absolute_uri(event, 'presale:event.index'), thumb)
|
||||
return urljoin(eventreverse_absolute(event, 'presale:event.index'), thumb)
|
||||
|
||||
|
||||
class WidgetAPIProductList(EventListMixin, View):
|
||||
@@ -547,7 +547,7 @@ class WidgetAPIProductList(EventListMixin, View):
|
||||
'location': str(ev.location),
|
||||
'date_range': self._get_date_range(ev, event, tz=tz),
|
||||
'availability': self._get_availability(ev, event, tz=tz),
|
||||
'event_url': build_absolute_uri(event, 'presale:event.index'),
|
||||
'event_url': eventreverse_absolute(event, 'presale:event.index'),
|
||||
'subevent': ev.pk if isinstance(ev, SubEvent) else None,
|
||||
})
|
||||
return events
|
||||
@@ -748,7 +748,7 @@ class WidgetAPIProductList(EventListMixin, View):
|
||||
'location': str(ev.location),
|
||||
'date_range': self._get_date_range(ev, ev.event, tz),
|
||||
'availability': self._get_availability(ev, ev.event, tz=tz),
|
||||
'event_url': build_absolute_uri(ev.event, 'presale:event.index'),
|
||||
'event_url': eventreverse_absolute(ev.event, 'presale:event.index'),
|
||||
'subevent': ev.pk,
|
||||
} for ev in evs
|
||||
]
|
||||
@@ -771,7 +771,7 @@ class WidgetAPIProductList(EventListMixin, View):
|
||||
'location': str(event.location),
|
||||
'date_range': dr,
|
||||
'availability': avail,
|
||||
'event_url': build_absolute_uri(event, 'presale:event.index'),
|
||||
'event_url': eventreverse_absolute(event, 'presale:event.index'),
|
||||
})
|
||||
|
||||
cache.set(cache_key, data, 30)
|
||||
@@ -796,7 +796,7 @@ class WidgetAPIProductList(EventListMixin, View):
|
||||
return self.response(cached_data)
|
||||
|
||||
data = {
|
||||
'target_url': build_absolute_uri(request.event, 'presale:event.index'),
|
||||
'target_url': eventreverse_absolute(request.event, 'presale:event.index'),
|
||||
'subevent': self.subevent.pk if self.subevent else None,
|
||||
'currency': request.event.currency,
|
||||
'display_net_prices': request.event.settings.display_net_prices,
|
||||
|
||||
@@ -174,15 +174,16 @@ function async_task_error(jqXHR, textStatus, errorThrown) {
|
||||
var respdom = $(jqXHR.responseText);
|
||||
var c = respdom.filter('.container');
|
||||
if (respdom.filter('form') && (respdom.filter('.has-error') || respdom.filter('.alert-danger'))) {
|
||||
// This is a failed form validation, let's just use it
|
||||
|
||||
if (respdom.filter('#page-wrapper') && $('#page-wrapper').length) {
|
||||
// This is a failed form validation, let's just use it
|
||||
async_task_replace_page("#page-wrapper", respdom.find("#page-wrapper").html());
|
||||
} else {
|
||||
async_task_replace_page("body", jqXHR.responseText.substring(
|
||||
jqXHR.responseText.indexOf("<body"),
|
||||
jqXHR.responseText.indexOf("</body")
|
||||
));
|
||||
document.dispatchEvent(new Event("pretix:async-task-error"))
|
||||
|
||||
}
|
||||
|
||||
} else if (c.length > 0) {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
document.getElementById('goback').onclick =
|
||||
function() {window.history.back()};
|
||||
|
||||
document.getElementById('reload').onclick =
|
||||
function() {window.location.reload(true)};
|
||||
['DOMContentLoaded', 'pretix:async-task-error'].forEach(function (ev) {
|
||||
document.addEventListener(ev, function () {
|
||||
document.querySelectorAll('#goback, #reload').forEach(function (element) {
|
||||
const regularLoad = ev === 'DOMContentLoaded' && element.id === 'goback';
|
||||
element.addEventListener('click', regularLoad
|
||||
? () => window.history.back()
|
||||
: () => window.location.reload()
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2051,9 +2051,16 @@ var shared_root_methods = {
|
||||
this.$root.set_cart_id(data.cart_id);
|
||||
this.$root.overlay.frame_loading = false;
|
||||
callback()
|
||||
}, () => {
|
||||
}, (xhr, data) => {
|
||||
if (xhr.status === 429 && typeof xhr.responseURL !== "undefined") {
|
||||
this.$root.overlay.error_message = strings['cart_error_429'];
|
||||
this.$root.overlay.frame_loading = false;
|
||||
this.$root.overlay.error_url_after = this.$root.newTabTarget;
|
||||
this.$root.overlay.error_url_after_new_tab = true;
|
||||
} else {
|
||||
this.$root.overlay.error_message = strings['cart_error'];
|
||||
this.$root.overlay.frame_loading = false;
|
||||
}
|
||||
})
|
||||
},
|
||||
get_cart_id: function() {
|
||||
@@ -2142,7 +2149,14 @@ var shared_root_computed = {
|
||||
if (this.subevent) {
|
||||
target = this.target_url + this.subevent + '/';
|
||||
}
|
||||
return target;
|
||||
var parameters = this.$root.consent_parameter
|
||||
if (this.$root.additionalURLParams) {
|
||||
parameters += `&${this.$root.additionalURLParams}`
|
||||
}
|
||||
if (parameters) {
|
||||
target += '?' + parameters.replace(/^&/, '')
|
||||
}
|
||||
return target
|
||||
},
|
||||
useIframe: function () {
|
||||
if (window.crossOriginIsolated === true) {
|
||||
|
||||
@@ -162,7 +162,15 @@ export function createWidgetStore (config: {
|
||||
return params.toString()
|
||||
},
|
||||
newTabTarget (): string {
|
||||
return this.subevent ? `${this.targetUrl}${this.subevent}/` : this.targetUrl
|
||||
let url = this.subevent ? `${this.targetUrl}${this.subevent}/` : this.targetUrl
|
||||
let parameters = this.consentParameter
|
||||
if (this.additionalURLParams) {
|
||||
parameters += `&${this.additionalURLParams}`
|
||||
}
|
||||
if (parameters) {
|
||||
url += '?' + parameters.replace(/^&/, '')
|
||||
}
|
||||
return url
|
||||
},
|
||||
formTarget (): string {
|
||||
const isFirefox = navigator.userAgent.toLowerCase().includes('firefox')
|
||||
@@ -441,6 +449,7 @@ export function createWidgetStore (config: {
|
||||
this.overlay.frameLoading = false
|
||||
this.overlay.errorUrlAfter = this.newTabTarget
|
||||
this.overlay.errorUrlAfterNewTab = true
|
||||
return
|
||||
} else if (e.status === 405) {
|
||||
// Likely a redirect!
|
||||
this.targetUrl = e.responseUrl.substring(0, e.responseUrl.indexOf('/cart/add') - 18)
|
||||
@@ -460,11 +469,18 @@ export function createWidgetStore (config: {
|
||||
this.overlay.frameLoading = true
|
||||
const data = await createCart(url)
|
||||
this.setCartId(data.cart_id)
|
||||
return true
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && (e.status === 200 || (e.status >= 400 && e.status < 500))) {
|
||||
if (e instanceof ApiError && e.status === 429) {
|
||||
this.overlay.errorMessage = STRINGS.cart_error_429
|
||||
this.overlay.frameLoading = false
|
||||
this.overlay.errorUrlAfter = this.newTabTarget
|
||||
this.overlay.errorUrlAfterNewTab = true
|
||||
} else if (e instanceof ApiError && (e.status === 200 || (e.status >= 400 && e.status < 500))) {
|
||||
this.overlay.errorMessage = STRINGS.cart_error
|
||||
this.overlay.frameLoading = false
|
||||
}
|
||||
return false
|
||||
}
|
||||
},
|
||||
redeem (voucherCode: string, event?: Event) {
|
||||
@@ -484,7 +500,7 @@ export function createWidgetStore (config: {
|
||||
async resume () {
|
||||
if (!this.cartId && this.keepCart) {
|
||||
// create an empty cart whose id we can persist
|
||||
await this.createCart()
|
||||
if (!await this.createCart()) return
|
||||
}
|
||||
let redirectUrl = `${this.targetUrl}w/${globalWidgetId}/`
|
||||
if (this.subevent && this.isButton && this.items.length === 0) {
|
||||
|
||||
@@ -243,6 +243,9 @@ def test_full_clone_cross_organizer_differences():
|
||||
sc1_c = organizer.sales_channels.create(identifier="c")
|
||||
sc2_a = organizer2.sales_channels.get(identifier="web")
|
||||
sc2_c = organizer2.sales_channels.create(identifier="c")
|
||||
o1_meta_prop_a = organizer.meta_properties.create(name="Prop to copy")
|
||||
o1_meta_prop_b = organizer.meta_properties.create(name="Prop to find")
|
||||
o2_meta_prop_b = organizer2.meta_properties.create(name="Prop to find")
|
||||
|
||||
event = Event.objects.create(
|
||||
organizer=organizer, name='Dummy', slug='dummy',
|
||||
@@ -267,6 +270,9 @@ def test_full_clone_cross_organizer_differences():
|
||||
event.settings.payment_giftcard__enabled = True
|
||||
event.settings.payment_giftcard__restrict_to_sales_channels = ['web', 'b', 'c']
|
||||
|
||||
event.meta_values.create(property=o1_meta_prop_a, value='a')
|
||||
event.meta_values.create(property=o1_meta_prop_b, value='b')
|
||||
|
||||
copied_event = Event.objects.create(
|
||||
organizer=organizer2, name='Dummy2', slug='dummy2',
|
||||
date_from=datetime.datetime(2022, 4, 15, 9, 0, 0, tzinfo=datetime.timezone.utc),
|
||||
@@ -289,3 +295,9 @@ def test_full_clone_cross_organizer_differences():
|
||||
|
||||
assert event.settings.get('payment_giftcard__restrict_to_sales_channels', as_type=list) == ['web', 'b', 'c']
|
||||
assert copied_event.settings.get('payment_giftcard__restrict_to_sales_channels', as_type=list) == ['web', 'c']
|
||||
|
||||
assert event.meta_values.get(property__name=o1_meta_prop_a.name).property.organizer == organizer
|
||||
assert copied_event.meta_values.get(property__name=o1_meta_prop_a.name).value == 'a'
|
||||
assert copied_event.meta_values.get(property__name=o1_meta_prop_a.name).property.organizer == organizer2
|
||||
assert copied_event.meta_values.get(property=o2_meta_prop_b).value == 'b'
|
||||
assert copied_event.meta_values.get(property=o2_meta_prop_b).property.organizer == organizer2
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import pytest
|
||||
from django.core.exceptions import SuspiciousFileOperation
|
||||
from reportlab.platypus import Paragraph
|
||||
|
||||
|
||||
def test_http_access_disabled(monkeypatch):
|
||||
def guard(*args, **kwargs):
|
||||
pytest.fail("No internet wanted!")
|
||||
|
||||
monkeypatch.setattr('socket.socket', guard)
|
||||
|
||||
with pytest.raises(SuspiciousFileOperation, match="should not be reading images from disk"):
|
||||
Paragraph(
|
||||
'<img src="https://static.pretix.cloud/static/pretixeu/img/opengraph.png"/>',
|
||||
)
|
||||
|
||||
|
||||
def test_file_access_disabled_scheme(monkeypatch):
|
||||
with pytest.raises(SuspiciousFileOperation, match="should not be reading images from disk"):
|
||||
Paragraph(
|
||||
'<img src="file:///etc/passwd" />',
|
||||
)
|
||||
|
||||
|
||||
def test_file_access_disabled_direct(monkeypatch):
|
||||
with pytest.raises(SuspiciousFileOperation, match="should not be reading images from disk"):
|
||||
Paragraph(
|
||||
'<img src="/etc/passwd" />',
|
||||
)
|
||||
@@ -22,17 +22,17 @@
|
||||
from django import urls
|
||||
from django.test import override_settings
|
||||
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.helpers.urls import mainreverse_absolute
|
||||
|
||||
|
||||
def test_site_url_domain():
|
||||
with override_settings(SITE_URL='https://example.com'):
|
||||
assert build_absolute_uri('control:auth.login') == 'https://example.com/control/login'
|
||||
assert mainreverse_absolute('control:auth.login') == 'https://example.com/control/login'
|
||||
|
||||
|
||||
def test_site_url_subpath():
|
||||
with override_settings(SITE_URL='https://example.com/presale'):
|
||||
old_prefix = urls.get_script_prefix()
|
||||
urls.set_script_prefix('/presale/')
|
||||
assert build_absolute_uri('control:auth.login') == 'https://example.com/presale/control/login'
|
||||
assert mainreverse_absolute('control:auth.login') == 'https://example.com/presale/control/login'
|
||||
urls.set_script_prefix(old_prefix)
|
||||
|
||||
@@ -26,7 +26,7 @@ from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.models import Event, Organizer
|
||||
from pretix.multidomain.models import KnownDomain
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
|
||||
from pretix.multidomain.urlreverse import eventreverse, eventreverse_absolute
|
||||
from pretix.testutils.queries import assert_num_queries
|
||||
|
||||
|
||||
@@ -248,20 +248,20 @@ def test_event_custom_domain_cache_clear(env):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_event_main_domain_absolute(env):
|
||||
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://example.com/mrmcd/2015/'
|
||||
assert eventreverse_absolute(env[1], 'presale:event.index') == 'http://example.com/mrmcd/2015/'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_event_custom_domain_absolute(env):
|
||||
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
|
||||
KnownDomain.objects.create(domainname='barfoo', organizer=env[0], event=env[1])
|
||||
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://barfoo/'
|
||||
assert eventreverse_absolute(env[1], 'presale:event.index') == 'http://barfoo/'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_event_org_domain_absolute(env):
|
||||
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
|
||||
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://foobar/2015/'
|
||||
assert eventreverse_absolute(env[1], 'presale:event.index') == 'http://foobar/2015/'
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -269,4 +269,4 @@ def test_event_org_alt_domain_absolute(env):
|
||||
KnownDomain.objects.create(domainname='foobar', organizer=env[0])
|
||||
d = KnownDomain.objects.create(domainname='altfoo', organizer=env[0], mode=KnownDomain.MODE_ORG_ALT_DOMAIN)
|
||||
d.event_assignments.create(event=env[1])
|
||||
assert build_absolute_uri(env[1], 'presale:event.index') == 'http://altfoo/2015/'
|
||||
assert eventreverse_absolute(env[1], 'presale:event.index') == 'http://altfoo/2015/'
|
||||
|
||||
Reference in New Issue
Block a user