mirror of
https://github.com/pretix/pretix.git
synced 2025-12-05 21:32:28 +00:00
Compare commits
65 Commits
794-questi
...
django22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c0214f334 | ||
|
|
3b4261884e | ||
|
|
68033e5d7d | ||
|
|
f14c12546d | ||
|
|
289878689b | ||
|
|
80a2e80b1c | ||
|
|
cb531a7a6a | ||
|
|
d5820d74d3 | ||
|
|
b686978074 | ||
|
|
c372bffc57 | ||
|
|
282c6108bf | ||
|
|
f2437c7ff7 | ||
|
|
dd0b6e6647 | ||
|
|
f3128591d8 | ||
|
|
d395db8142 | ||
|
|
0c82e92882 | ||
|
|
db0c13a3c2 | ||
|
|
19a2f4163a | ||
|
|
76526465c0 | ||
|
|
d0d0f9aa4c | ||
|
|
482f6b1eb8 | ||
|
|
327418299a | ||
|
|
5dfd1e6337 | ||
|
|
bc01124584 | ||
|
|
c0df418265 | ||
|
|
af06f6fc38 | ||
|
|
4c0e8f69ea | ||
|
|
243e4ac4c8 | ||
|
|
b931d27486 | ||
|
|
2810e2a760 | ||
|
|
04465393b2 | ||
|
|
4c9032f2a8 | ||
|
|
cae2bb944a | ||
|
|
724e745b8d | ||
|
|
f4cead1c20 | ||
|
|
7cab1924bb | ||
|
|
641148fecc | ||
|
|
9b3860e5fd | ||
|
|
cb9d4c10df | ||
|
|
84105b9585 | ||
|
|
3f38caeb24 | ||
|
|
eae552e474 | ||
|
|
f27c10c2ac | ||
|
|
abd237b969 | ||
|
|
99c61c9060 | ||
|
|
246f307e21 | ||
|
|
1f672e7df2 | ||
|
|
b261a2041a | ||
|
|
2d37c6d94d | ||
|
|
e75ae80fb5 | ||
|
|
73ec5bac79 | ||
|
|
46166159b0 | ||
|
|
598693fab2 | ||
|
|
2420d884fc | ||
|
|
f95005a8d4 | ||
|
|
e773096df3 | ||
|
|
c42905421d | ||
|
|
46c2e28def | ||
|
|
07bc3df6d3 | ||
|
|
2992c4c48a | ||
|
|
c53718381e | ||
|
|
98e5f0b95d | ||
|
|
7f11f06f3f | ||
|
|
949057a9cc | ||
|
|
edd643cc32 |
17
.travis.yml
17
.travis.yml
@@ -1,4 +1,5 @@
|
||||
language: python
|
||||
dist: xenial
|
||||
sudo: false
|
||||
install:
|
||||
- pip install -U pip wheel setuptools
|
||||
@@ -12,23 +13,23 @@ services:
|
||||
- postgresql
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_sqlite.cfg
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=tests-cov PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=style
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=plugins
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=doc-spelling
|
||||
- python: 3.6
|
||||
- python: 3.7
|
||||
env: JOB=translation-spelling
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
|
||||
@@ -68,10 +68,6 @@ To build and run pretix, you will need the following debian packages::
|
||||
python3-dev libxml2-dev libxslt1-dev libffi-dev zlib1g-dev libssl-dev \
|
||||
gettext libpq-dev libmariadbclient-dev libjpeg-dev libopenjp2-7-dev
|
||||
|
||||
.. note:: Python 3.7 is not yet supported, so if you run a very recent OS, make sure to get
|
||||
Python 3.6 from somewhere. You can check the current state of things in our
|
||||
`Python 3.7 issue`_.
|
||||
|
||||
Config file
|
||||
-----------
|
||||
|
||||
@@ -314,4 +310,3 @@ example::
|
||||
.. _redis: https://blog.programster.org/debian-8-install-redis-server/
|
||||
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
|
||||
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
.. _Python 3.7 issue: https://github.com/pretix/pretix/issues/1025
|
||||
|
||||
@@ -181,4 +181,37 @@ as the string values ``true`` and ``false``.
|
||||
If the ``ordering`` parameter is documented for a resource, you can use it to sort the result set by one of the allowed
|
||||
fields. Prepend a ``-`` to the field name to reverse the sort order.
|
||||
|
||||
|
||||
Idempotency
|
||||
-----------
|
||||
|
||||
Our API supports an idempotency mechanism to make sure you can safely retry operations without accidentally performing
|
||||
them twice. This is useful if an API call experiences interruptions in transit, e.g. due to a network failure, and you
|
||||
do not know if it completed successfully.
|
||||
|
||||
To perform an idempotent request, add a ``X-Idempotency-Key`` header with a random string value (we recommend a version
|
||||
4 UUID) to your request. If we see a second request with the same ``X-Idempotency-Key`` and the same ``Authorization``
|
||||
and ``Cookie`` headers, we will not perform the action for a second time but return the exact same response instead.
|
||||
|
||||
Please note that this also goes for most error responses. For example, if we returned you a ``403 Permission Denied``
|
||||
error and you retry with the same ``X-Idempotency-Key``, you will get the same error again, even if you were granted
|
||||
permission in the meantime! This includes internal server errors on our side that might have been fixed in the meantime.
|
||||
|
||||
There are only three exceptions to the rule:
|
||||
|
||||
* Responses with status code ``409 Conflict`` are not cached. If you send the request again, it will be executed as a
|
||||
new request, since these responses are intended to be retried.
|
||||
|
||||
* Rate-limited responses with status code ``429 Too Many Requests`` are not cached and you can safely retry them.
|
||||
|
||||
* Responses with status code ``503 Service Unavailable`` are not cached and you can safely retry them.
|
||||
|
||||
If you send a request with an ``X-Idempotency-Key`` header that we have seen before but that has not yet received a
|
||||
response, you will receive a response with status code ``409 Conflict`` and are asked to retry after five seconds.
|
||||
|
||||
We store idempotency keys for 24 hours, so you should never retry a request after a longer time period.
|
||||
|
||||
All ``POST``, ``PUT``, ``PATCH``, or ``DELETE`` api calls support idempotency keys. Adding an idempotency key to a
|
||||
``GET``, ``HEAD``, or ``OPTIONS`` request has no effect.
|
||||
|
||||
.. _CSRF policies: https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax
|
||||
|
||||
@@ -373,8 +373,8 @@ List of all orders
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``code`` and
|
||||
``status``. Default: ``datetime``
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``code``,
|
||||
``last_modified``, and ``status``. Default: ``datetime``
|
||||
:query string code: Only return orders that match the given order code
|
||||
:query string status: Only return orders in the given order status (see above)
|
||||
:query boolean testmode: Only return orders with ``testmode`` set to ``true`` or ``false``
|
||||
@@ -385,6 +385,7 @@ List of all orders
|
||||
:query datetime modified_since: Only return orders that have changed since the given date. Be careful: We only
|
||||
recommend using this in combination with ``testmode=false``, since test mode orders can vanish at any time and
|
||||
you will not notice it using this method.
|
||||
:query datetime created_since: Only return orders that have been created since the given date.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:resheader X-Page-Generated: The server time at the beginning of the operation. If you're using this API to fetch
|
||||
@@ -749,6 +750,7 @@ Creating orders
|
||||
should only use this if you know the specific payment provider in detail. Please keep in mind that the payment
|
||||
provider will not be called to do anything about this (i.e. if you pass a bank account to a debit provider, *no*
|
||||
charge will be created), this is just informative in case you *handled the payment already*.
|
||||
* ``payment_date`` (optional) – Date and time of the completion of the payment.
|
||||
* ``comment`` (optional)
|
||||
* ``checkin_attention`` (optional)
|
||||
* ``invoice_address`` (optional)
|
||||
@@ -788,6 +790,8 @@ Creating orders
|
||||
* ``internal_type``
|
||||
* ``tax_rule``
|
||||
|
||||
* ``force`` (optional). If set to ``true``, quotas will be ignored.
|
||||
|
||||
If you want to use add-on products, you need to set the ``positionid`` fields of all positions manually
|
||||
to incrementing integers starting with ``1``. Then, you can reference one of these
|
||||
IDs in the ``addon_to`` field of another position. Note that all add_ons for a specific position need to come
|
||||
|
||||
@@ -20,7 +20,7 @@ Order events
|
||||
There are multiple signals that will be sent out in the ordering cycle:
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: validate_cart, order_fee_calculation, order_paid, order_placed, order_fee_type_name, allow_ticket_download
|
||||
:members: validate_cart, order_fee_calculation, order_paid, order_placed, order_canceled, order_expired, order_modified, order_changed, order_approved, order_denied, order_fee_type_name, allow_ticket_download
|
||||
|
||||
Frontend
|
||||
--------
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "2.6.0.dev0"
|
||||
__version__ = "2.6.0"
|
||||
|
||||
@@ -19,7 +19,7 @@ class DeviceTokenAuthentication(TokenAuthentication):
|
||||
if not device.initialized:
|
||||
raise exceptions.AuthenticationFailed('Device has not been initialized.')
|
||||
|
||||
if not device.api_token:
|
||||
if device.revoked:
|
||||
raise exceptions.AuthenticationFailed('Device access has been revoked.')
|
||||
|
||||
return AnonymousUser(), device
|
||||
|
||||
91
src/pretix/api/middleware.py
Normal file
91
src/pretix/api/middleware.py
Normal file
@@ -0,0 +1,91 @@
|
||||
import json
|
||||
from hashlib import sha1
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.http import HttpRequest, HttpResponse, JsonResponse
|
||||
from django.utils.timezone import now
|
||||
from rest_framework import status
|
||||
|
||||
from pretix.api.models import ApiCall
|
||||
|
||||
|
||||
class IdempotencyMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request: HttpRequest):
|
||||
if request.method in ('GET', 'HEAD', 'OPTIONS'):
|
||||
return self.get_response(request)
|
||||
|
||||
if not request.path.startswith('/api/'):
|
||||
return self.get_response(request)
|
||||
|
||||
if not request.headers.get('X-Idempotency-Key'):
|
||||
return self.get_response(request)
|
||||
|
||||
auth_hash_parts = '{}:{}'.format(
|
||||
request.headers.get('Authorization', ''),
|
||||
request.COOKIES.get(settings.SESSION_COOKIE_NAME, '')
|
||||
)
|
||||
auth_hash = sha1(auth_hash_parts.encode()).hexdigest()
|
||||
idempotency_key = request.headers.get('X-Idempotency-Key', '')
|
||||
|
||||
with transaction.atomic():
|
||||
call, created = ApiCall.objects.select_for_update().get_or_create(
|
||||
auth_hash=auth_hash,
|
||||
idempotency_key=idempotency_key,
|
||||
defaults={
|
||||
'locked': now(),
|
||||
'request_method': request.method,
|
||||
'request_path': request.path,
|
||||
'response_code': 0,
|
||||
'response_headers': '{}',
|
||||
'response_body': b''
|
||||
}
|
||||
)
|
||||
|
||||
if created:
|
||||
resp = self.get_response(request)
|
||||
with transaction.atomic():
|
||||
if resp.status_code in (409, 429, 503):
|
||||
# This is the exception: These calls are *meant* to be retried!
|
||||
call.delete()
|
||||
else:
|
||||
call.response_code = resp.status_code
|
||||
if isinstance(resp.content, str):
|
||||
call.response_body = resp.content.encode()
|
||||
elif isinstance(resp.content, memoryview):
|
||||
call.response_body = resp.content.tobytes()
|
||||
elif isinstance(resp.content, bytes):
|
||||
call.response_body = resp.content
|
||||
elif hasattr(resp.content, 'read'):
|
||||
call.response_body = resp.read()
|
||||
elif hasattr(resp, 'data'):
|
||||
call.response_body = json.dumps(resp.data)
|
||||
else:
|
||||
call.response_body = repr(resp).encode()
|
||||
call.response_headers = json.dumps(resp._headers)
|
||||
call.locked = None
|
||||
call.save(update_fields=['locked', 'response_code', 'response_headers',
|
||||
'response_body'])
|
||||
return resp
|
||||
else:
|
||||
if call.locked:
|
||||
r = JsonResponse(
|
||||
{'detail': 'Concurrent request with idempotency key.'},
|
||||
status=status.HTTP_409_CONFLICT,
|
||||
)
|
||||
r['Retry-After'] = 5
|
||||
return r
|
||||
|
||||
content = call.response_body
|
||||
if isinstance(content, memoryview):
|
||||
content = content.tobytes()
|
||||
r = HttpResponse(
|
||||
content=content,
|
||||
status=call.response_code,
|
||||
)
|
||||
for k, v in json.loads(call.response_headers).values():
|
||||
r[k] = v
|
||||
return r
|
||||
44
src/pretix/api/migrations/0004_auto_20190405_1048.py
Normal file
44
src/pretix/api/migrations/0004_auto_20190405_1048.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# Generated by Django 2.1.5 on 2019-04-05 10:48
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('pretixbase', '0116_auto_20190402_0722'),
|
||||
('pretixapi', '0003_webhook_webhookcall_webhookeventlistener'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ApiCall',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('idempotency_key', models.CharField(db_index=True, max_length=190)),
|
||||
('auth_hash', models.CharField(db_index=True, max_length=190)),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('locked', models.DateTimeField(null=True)),
|
||||
('request_method', models.CharField(max_length=20)),
|
||||
('request_path', models.CharField(max_length=255)),
|
||||
('response_code', models.PositiveIntegerField()),
|
||||
('response_headers', models.TextField()),
|
||||
('response_body', models.BinaryField()),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='webhookcall',
|
||||
options={'ordering': ('-datetime',)},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='webhookeventlistener',
|
||||
options={'ordering': ('action_type',)},
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='apicall',
|
||||
unique_together={('idempotency_key', 'auth_hash')},
|
||||
),
|
||||
]
|
||||
@@ -77,6 +77,9 @@ class WebHook(models.Model):
|
||||
all_events = models.BooleanField(default=True, verbose_name=_("All events (including newly created ones)"))
|
||||
limit_events = models.ManyToManyField('pretixbase.Event', verbose_name=_("Limit to events"), blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ('id',)
|
||||
|
||||
@property
|
||||
def action_types(self):
|
||||
return [
|
||||
@@ -106,3 +109,20 @@ class WebHookCall(models.Model):
|
||||
|
||||
class Meta:
|
||||
ordering = ("-datetime",)
|
||||
|
||||
|
||||
class ApiCall(models.Model):
|
||||
idempotency_key = models.CharField(max_length=190, db_index=True)
|
||||
auth_hash = models.CharField(max_length=190, db_index=True)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
locked = models.DateTimeField(null=True)
|
||||
|
||||
request_method = models.CharField(max_length=20)
|
||||
request_path = models.CharField(max_length=255)
|
||||
|
||||
response_code = models.PositiveIntegerField()
|
||||
response_headers = models.TextField()
|
||||
response_body = models.BinaryField()
|
||||
|
||||
class Meta:
|
||||
unique_together = (('idempotency_key', 'auth_hash'),)
|
||||
|
||||
@@ -31,10 +31,10 @@ class PluginsField(Field):
|
||||
def to_representation(self, obj):
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
|
||||
return {
|
||||
return sorted([
|
||||
p.module for p in get_all_plugins()
|
||||
if not p.name.startswith('.') and getattr(p, 'visible', True) and p.module in obj.get_plugins()
|
||||
}
|
||||
])
|
||||
|
||||
def to_internal_value(self, data):
|
||||
return {
|
||||
|
||||
@@ -457,11 +457,13 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
payment_provider = serializers.CharField(required=True)
|
||||
payment_info = CompatibleJSONField(required=False)
|
||||
consume_carts = serializers.ListField(child=serializers.CharField(), required=False)
|
||||
force = serializers.BooleanField(default=False, required=False)
|
||||
payment_date = serializers.DateTimeField(required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ('code', 'status', 'testmode', 'email', 'locale', 'payment_provider', 'fees', 'comment', 'sales_channel',
|
||||
'invoice_address', 'positions', 'checkin_attention', 'payment_info', 'consume_carts')
|
||||
'invoice_address', 'positions', 'checkin_attention', 'payment_info', 'payment_date', 'consume_carts', 'force')
|
||||
|
||||
def validate_payment_provider(self, pp):
|
||||
if pp not in self.context['event'].get_payment_providers():
|
||||
@@ -532,6 +534,8 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
positions_data = validated_data.pop('positions') if 'positions' in validated_data else []
|
||||
payment_provider = validated_data.pop('payment_provider')
|
||||
payment_info = validated_data.pop('payment_info', '{}')
|
||||
payment_date = validated_data.pop('payment_date', now())
|
||||
force = validated_data.pop('force', False)
|
||||
|
||||
if 'invoice_address' in validated_data:
|
||||
iadata = validated_data.pop('invoice_address')
|
||||
@@ -565,29 +569,30 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
|
||||
errs = [{} for p in positions_data]
|
||||
|
||||
for i, pos_data in enumerate(positions_data):
|
||||
new_quotas = (pos_data.get('variation').quotas.filter(subevent=pos_data.get('subevent'))
|
||||
if pos_data.get('variation')
|
||||
else pos_data.get('item').quotas.filter(subevent=pos_data.get('subevent')))
|
||||
if len(new_quotas) == 0:
|
||||
errs[i]['item'] = [ugettext_lazy('The product "{}" is not assigned to a quota.').format(
|
||||
str(pos_data.get('item'))
|
||||
)]
|
||||
else:
|
||||
for quota in new_quotas:
|
||||
if quota not in quota_avail_cache:
|
||||
quota_avail_cache[quota] = list(quota.availability())
|
||||
if not force:
|
||||
for i, pos_data in enumerate(positions_data):
|
||||
new_quotas = (pos_data.get('variation').quotas.filter(subevent=pos_data.get('subevent'))
|
||||
if pos_data.get('variation')
|
||||
else pos_data.get('item').quotas.filter(subevent=pos_data.get('subevent')))
|
||||
if len(new_quotas) == 0:
|
||||
errs[i]['item'] = [ugettext_lazy('The product "{}" is not assigned to a quota.').format(
|
||||
str(pos_data.get('item'))
|
||||
)]
|
||||
else:
|
||||
for quota in new_quotas:
|
||||
if quota not in quota_avail_cache:
|
||||
quota_avail_cache[quota] = list(quota.availability())
|
||||
|
||||
if quota_avail_cache[quota][1] is not None:
|
||||
quota_avail_cache[quota][1] -= 1
|
||||
if quota_avail_cache[quota][1] < 0:
|
||||
errs[i]['item'] = [
|
||||
ugettext_lazy('There is not enough quota available on quota "{}" to perform the operation.').format(
|
||||
quota.name
|
||||
)
|
||||
]
|
||||
if quota_avail_cache[quota][1] is not None:
|
||||
quota_avail_cache[quota][1] -= 1
|
||||
if quota_avail_cache[quota][1] < 0:
|
||||
errs[i]['item'] = [
|
||||
ugettext_lazy('There is not enough quota available on quota "{}" to perform the operation.').format(
|
||||
quota.name
|
||||
)
|
||||
]
|
||||
|
||||
quotadiff.update(new_quotas)
|
||||
quotadiff.update(new_quotas)
|
||||
|
||||
if any(errs):
|
||||
raise ValidationError({'positions': errs})
|
||||
@@ -614,7 +619,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
amount=order.total,
|
||||
provider=payment_provider,
|
||||
info=payment_info,
|
||||
payment_date=now(),
|
||||
payment_date=payment_date,
|
||||
state=OrderPayment.PAYMENT_STATE_CONFIRMED
|
||||
)
|
||||
elif payment_provider:
|
||||
|
||||
@@ -3,7 +3,7 @@ from datetime import timedelta
|
||||
from django.dispatch import Signal, receiver
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.api.models import WebHookCall
|
||||
from pretix.api.models import ApiCall, WebHookCall
|
||||
from pretix.base.signals import periodic_task
|
||||
|
||||
register_webhook_events = Signal(
|
||||
@@ -19,3 +19,8 @@ instances.
|
||||
@receiver(periodic_task)
|
||||
def cleanup_webhook_logs(sender, **kwargs):
|
||||
WebHookCall.objects.filter(datetime__lte=now() - timedelta(days=30)).delete()
|
||||
|
||||
|
||||
@receiver(periodic_task)
|
||||
def cleanup_api_logs(sender, **kwargs):
|
||||
ApiCall.objects.filter(datetime__lte=now() - timedelta(hours=24)).delete()
|
||||
|
||||
@@ -31,10 +31,10 @@ class RichOrderingFilter(OrderingFilter):
|
||||
class ConditionalListView:
|
||||
|
||||
def list(self, request, **kwargs):
|
||||
if_modified_since = request.META.get('HTTP_IF_MODIFIED_SINCE')
|
||||
if_modified_since = request.headers.get('If-Modified-Since')
|
||||
if if_modified_since:
|
||||
if_modified_since = parse_http_date_safe(if_modified_since)
|
||||
if_unmodified_since = request.META.get('HTTP_IF_UNMODIFIED_SINCE')
|
||||
if_unmodified_since = request.headers.get('If-Unmodified-Since')
|
||||
if if_unmodified_since:
|
||||
if_unmodified_since = parse_http_date_safe(if_unmodified_since)
|
||||
if not hasattr(request, 'event'):
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.fields import DateTimeField
|
||||
from rest_framework.response import Response
|
||||
|
||||
@@ -77,7 +77,7 @@ class CheckinListViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
super().perform_destroy(instance)
|
||||
|
||||
@detail_route(methods=['GET'])
|
||||
@action(detail=True, methods=['GET'])
|
||||
def status(self, *args, **kwargs):
|
||||
clist = self.get_object()
|
||||
cqs = Checkin.objects.filter(
|
||||
@@ -242,7 +242,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
|
||||
return qs
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def redeem(self, *args, **kwargs):
|
||||
force = bool(self.request.data.get('force', False))
|
||||
ignore_unpaid = bool(self.request.data.get('ignore_unpaid', False))
|
||||
|
||||
@@ -105,7 +105,7 @@ class RevokeKeyView(APIView):
|
||||
|
||||
def post(self, request, format=None):
|
||||
device = request.auth
|
||||
device.api_token = None
|
||||
device.revoked = True
|
||||
device.save()
|
||||
device.log_action('pretix.device.revoked', auth=device)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from pretix.api.serializers.event import (
|
||||
)
|
||||
from pretix.api.views import ConditionalListView
|
||||
from pretix.base.models import (
|
||||
Device, Event, ItemCategory, TaxRule, TeamAPIToken,
|
||||
CartPosition, Device, Event, ItemCategory, TaxRule, TeamAPIToken,
|
||||
)
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
@@ -272,6 +272,8 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
auth=self.request.auth,
|
||||
data=self.request.data
|
||||
)
|
||||
CartPosition.objects.filter(addon_to__subevent=instance).delete()
|
||||
instance.cartposition_set.all().delete()
|
||||
super().perform_destroy(instance)
|
||||
except ProtectedError:
|
||||
raise PermissionDenied('The sub-event could not be deleted as some constraints (e.g. data created by '
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.shortcuts import get_object_or_404
|
||||
from django.utils.functional import cached_property
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.response import Response
|
||||
@@ -16,8 +16,8 @@ from pretix.api.serializers.item import (
|
||||
)
|
||||
from pretix.api.views import ConditionalListView
|
||||
from pretix.base.models import (
|
||||
Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation, Question,
|
||||
QuestionOption, Quota,
|
||||
CartPosition, Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation,
|
||||
Question, QuestionOption, Quota,
|
||||
)
|
||||
from pretix.helpers.dicts import merge_dicts
|
||||
|
||||
@@ -84,7 +84,8 @@ class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
)
|
||||
self.get_object().cartposition_set.all().delete()
|
||||
CartPosition.objects.filter(addon_to__item=instance).delete()
|
||||
instance.cartposition_set.all().delete()
|
||||
super().perform_destroy(instance)
|
||||
|
||||
|
||||
@@ -498,7 +499,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
)
|
||||
super().perform_destroy(instance)
|
||||
|
||||
@detail_route(methods=['get'])
|
||||
@action(detail=True, methods=['get'])
|
||||
def availability(self, request, *args, **kwargs):
|
||||
quota = self.get_object()
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.utils.timezone import make_aware, now
|
||||
from django.utils.translation import ugettext as _
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from rest_framework import mixins, serializers, status, viewsets
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import (
|
||||
APIException, NotFound, PermissionDenied, ValidationError,
|
||||
)
|
||||
@@ -42,7 +42,9 @@ from pretix.base.services.orders import (
|
||||
extend_order, mark_order_expired, mark_order_refunded,
|
||||
)
|
||||
from pretix.base.services.tickets import generate
|
||||
from pretix.base.signals import order_placed, register_ticket_outputs
|
||||
from pretix.base.signals import (
|
||||
order_modified, order_placed, register_ticket_outputs,
|
||||
)
|
||||
|
||||
|
||||
class OrderFilter(FilterSet):
|
||||
@@ -50,6 +52,7 @@ class OrderFilter(FilterSet):
|
||||
code = django_filters.CharFilter(field_name='code', lookup_expr='iexact')
|
||||
status = django_filters.CharFilter(field_name='status', lookup_expr='iexact')
|
||||
modified_since = django_filters.IsoDateTimeFilter(field_name='last_modified', lookup_expr='gte')
|
||||
created_since = django_filters.IsoDateTimeFilter(field_name='datetime', lookup_expr='gte')
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
@@ -124,7 +127,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
serializer = self.get_serializer(queryset, many=True)
|
||||
return Response(serializer.data, headers={'X-Page-Generated': date})
|
||||
|
||||
@detail_route(url_name='download', url_path='download/(?P<output>[^/]+)')
|
||||
@action(detail=True, url_name='download', url_path='download/(?P<output>[^/]+)')
|
||||
def download(self, request, output, **kwargs):
|
||||
provider = self._get_output_provider(output)
|
||||
order = self.get_object()
|
||||
@@ -146,7 +149,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return resp
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def mark_paid(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
|
||||
@@ -187,7 +190,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def mark_canceled(self, request, **kwargs):
|
||||
send_mail = request.data.get('send_email', True)
|
||||
cancellation_fee = request.data.get('cancellation_fee', None)
|
||||
@@ -221,7 +224,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def approve(self, request, **kwargs):
|
||||
send_mail = request.data.get('send_email', True)
|
||||
|
||||
@@ -239,7 +242,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def deny(self, request, **kwargs):
|
||||
send_mail = request.data.get('send_email', True)
|
||||
comment = request.data.get('comment', '')
|
||||
@@ -257,7 +260,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def mark_pending(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
|
||||
@@ -276,7 +279,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def mark_expired(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
|
||||
@@ -293,7 +296,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def mark_refunded(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
|
||||
@@ -310,7 +313,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def create_invoice(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
has_inv = order.invoices.exists() and not (
|
||||
@@ -342,7 +345,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
status=status.HTTP_201_CREATED
|
||||
)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def resend_link(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
if not order.email:
|
||||
@@ -356,7 +359,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
status=status.HTTP_204_NO_CONTENT
|
||||
)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
@transaction.atomic
|
||||
def regenerate_secrets(self, request, **kwargs):
|
||||
order = self.get_object()
|
||||
@@ -374,7 +377,7 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def extend(self, request, **kwargs):
|
||||
new_date = request.data.get('expires', None)
|
||||
force = request.data.get('force', False)
|
||||
@@ -450,61 +453,64 @@ class OrderViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
return super().update(request, *args, **kwargs)
|
||||
|
||||
@transaction.atomic
|
||||
def perform_update(self, serializer):
|
||||
if 'comment' in self.request.data and serializer.instance.comment != self.request.data.get('comment'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.comment',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'new_comment': self.request.data.get('comment')
|
||||
}
|
||||
)
|
||||
with transaction.atomic():
|
||||
if 'comment' in self.request.data and serializer.instance.comment != self.request.data.get('comment'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.comment',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'new_comment': self.request.data.get('comment')
|
||||
}
|
||||
)
|
||||
|
||||
if 'checkin_attention' in self.request.data and serializer.instance.checkin_attention != self.request.data.get('checkin_attention'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.checkin_attention',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'new_value': self.request.data.get('checkin_attention')
|
||||
}
|
||||
)
|
||||
if 'checkin_attention' in self.request.data and serializer.instance.checkin_attention != self.request.data.get('checkin_attention'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.checkin_attention',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'new_value': self.request.data.get('checkin_attention')
|
||||
}
|
||||
)
|
||||
|
||||
if 'email' in self.request.data and serializer.instance.email != self.request.data.get('email'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.contact.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'old_email': serializer.instance.email,
|
||||
'new_email': self.request.data.get('email'),
|
||||
}
|
||||
)
|
||||
if 'email' in self.request.data and serializer.instance.email != self.request.data.get('email'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.contact.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'old_email': serializer.instance.email,
|
||||
'new_email': self.request.data.get('email'),
|
||||
}
|
||||
)
|
||||
|
||||
if 'locale' in self.request.data and serializer.instance.locale != self.request.data.get('locale'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.locale.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'old_locale': serializer.instance.locale,
|
||||
'new_locale': self.request.data.get('locale'),
|
||||
}
|
||||
)
|
||||
if 'locale' in self.request.data and serializer.instance.locale != self.request.data.get('locale'):
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.locale.changed',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'old_locale': serializer.instance.locale,
|
||||
'new_locale': self.request.data.get('locale'),
|
||||
}
|
||||
)
|
||||
|
||||
if 'invoice_address' in self.request.data:
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.modified',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'invoice_data': self.request.data.get('invoice_address'),
|
||||
}
|
||||
)
|
||||
|
||||
serializer.save()
|
||||
|
||||
if 'invoice_address' in self.request.data:
|
||||
serializer.instance.log_action(
|
||||
'pretix.event.order.modified',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={
|
||||
'invoice_data': self.request.data.get('invoice_address'),
|
||||
}
|
||||
)
|
||||
|
||||
serializer.save()
|
||||
order_modified.send(sender=serializer.instance.event, order=serializer.instance)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save()
|
||||
@@ -613,7 +619,7 @@ class OrderPositionViewSet(mixins.DestroyModelMixin, viewsets.ReadOnlyModelViewS
|
||||
return prov
|
||||
raise NotFound('Unknown output provider.')
|
||||
|
||||
@detail_route(url_name='download', url_path='download/(?P<output>[^/]+)')
|
||||
@action(detail=True, url_name='download', url_path='download/(?P<output>[^/]+)')
|
||||
def download(self, request, output, **kwargs):
|
||||
provider = self._get_output_provider(output)
|
||||
pos = self.get_object()
|
||||
@@ -664,7 +670,7 @@ class PaymentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
order = get_object_or_404(Order, code=self.kwargs['order'], event=self.request.event)
|
||||
return order.payments.all()
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def confirm(self, request, **kwargs):
|
||||
payment = self.get_object()
|
||||
force = request.data.get('force', False)
|
||||
@@ -685,7 +691,7 @@ class PaymentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
pass
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def refund(self, request, **kwargs):
|
||||
payment = self.get_object()
|
||||
amount = serializers.DecimalField(max_digits=10, decimal_places=2).to_internal_value(
|
||||
@@ -750,7 +756,7 @@ class PaymentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
payment.order.save(update_fields=['status', 'expires'])
|
||||
return Response(OrderRefundSerializer(r).data, status=status.HTTP_200_OK)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def cancel(self, request, **kwargs):
|
||||
payment = self.get_object()
|
||||
|
||||
@@ -778,7 +784,7 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
order = get_object_or_404(Order, code=self.kwargs['order'], event=self.request.event)
|
||||
return order.refunds.all()
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def cancel(self, request, **kwargs):
|
||||
refund = self.get_object()
|
||||
|
||||
@@ -795,7 +801,7 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
}, user=self.request.user if self.request.user.is_authenticated else None, auth=self.request.auth)
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def process(self, request, **kwargs):
|
||||
refund = self.get_object()
|
||||
|
||||
@@ -820,7 +826,7 @@ class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
refund.order.save(update_fields=['status', 'expires'])
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def done(self, request, **kwargs):
|
||||
refund = self.get_object()
|
||||
|
||||
@@ -910,7 +916,7 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
nr=Concat('prefix', 'invoice_no')
|
||||
)
|
||||
|
||||
@detail_route()
|
||||
@action(detail=True, )
|
||||
def download(self, request, **kwargs):
|
||||
invoice = self.get_object()
|
||||
|
||||
@@ -928,7 +934,7 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
resp['Content-Disposition'] = 'attachment; filename="{}.pdf"'.format(invoice.number)
|
||||
return resp
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def regenerate(self, request, **kwarts):
|
||||
inv = self.get_object()
|
||||
if inv.canceled:
|
||||
@@ -947,7 +953,7 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
)
|
||||
return Response(status=204)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def reissue(self, request, **kwarts):
|
||||
inv = self.get_object()
|
||||
if inv.canceled:
|
||||
|
||||
@@ -7,7 +7,7 @@ from django_filters.rest_framework import (
|
||||
BooleanFilter, DjangoFilterBackend, FilterSet,
|
||||
)
|
||||
from rest_framework import status, viewsets
|
||||
from rest_framework.decorators import list_route
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.response import Response
|
||||
@@ -111,9 +111,12 @@ class VoucherViewSet(viewsets.ModelViewSet):
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
)
|
||||
super().perform_destroy(instance)
|
||||
with transaction.atomic():
|
||||
instance.cartposition_set.filter(addon_to__isnull=False).delete()
|
||||
instance.cartposition_set.all().delete()
|
||||
super().perform_destroy(instance)
|
||||
|
||||
@list_route(methods=['POST'])
|
||||
@action(detail=False, methods=['POST'])
|
||||
def batch_create(self, request, *args, **kwargs):
|
||||
if any(self._predict_quota_check(d, None) for d in request.data):
|
||||
lockfn = request.event.lock
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import django_filters
|
||||
from django_filters.rest_framework import DjangoFilterBackend, FilterSet
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import detail_route
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import PermissionDenied, ValidationError
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.response import Response
|
||||
@@ -69,7 +69,7 @@ class WaitingListViewSet(viewsets.ModelViewSet):
|
||||
)
|
||||
super().perform_destroy(instance)
|
||||
|
||||
@detail_route(methods=['POST'])
|
||||
@action(detail=True, methods=['POST'])
|
||||
def send_voucher(self, *args, **kwargs):
|
||||
try:
|
||||
self.get_object().send_voucher(
|
||||
|
||||
@@ -97,7 +97,7 @@ def get_language_from_event(request: HttpRequest) -> str:
|
||||
|
||||
|
||||
def get_language_from_browser(request: HttpRequest) -> str:
|
||||
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
|
||||
accept = request.headers.get('Accept-Language', '')
|
||||
for accept_lang, unused in parse_accept_lang_header(accept):
|
||||
if accept_lang == '*':
|
||||
break
|
||||
|
||||
22
src/pretix/base/migrations/0116_auto_20190402_0722.py
Normal file
22
src/pretix/base/migrations/0116_auto_20190402_0722.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 2.1.5 on 2019-04-02 07:22
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0115_auto_20190323_2238'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='device',
|
||||
name='revoked',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -111,6 +111,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
|
||||
class Meta:
|
||||
verbose_name = _("User")
|
||||
verbose_name_plural = _("Users")
|
||||
ordering = ('email',)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.email = self.email.lower()
|
||||
|
||||
@@ -41,6 +41,7 @@ class Device(LoggedModel):
|
||||
api_token = models.CharField(max_length=190, unique=True, null=True)
|
||||
all_events = models.BooleanField(default=False, verbose_name=_("All events (including newly created ones)"))
|
||||
limit_events = models.ManyToManyField('Event', verbose_name=_("Limit to events"), blank=True)
|
||||
revoked = models.BooleanField(default=False)
|
||||
name = models.CharField(
|
||||
max_length=190,
|
||||
verbose_name=_('Name')
|
||||
|
||||
@@ -759,6 +759,7 @@ class Event(EventMixin, LoggedModel):
|
||||
return not self.orders.exists() and not self.invoices.exists()
|
||||
|
||||
def delete_sub_objects(self):
|
||||
self.cartposition_set.filter(addon_to__isnull=False).delete()
|
||||
self.cartposition_set.all().delete()
|
||||
self.items.all().delete()
|
||||
self.subevents.all().delete()
|
||||
|
||||
@@ -37,7 +37,7 @@ class MultiStringField(TextField):
|
||||
def get_prep_lookup(self, lookup_type, value): # NOQA
|
||||
raise TypeError('Lookups on multi strings are currently not supported.')
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
def from_db_value(self, value, expression, connection):
|
||||
if value:
|
||||
return [v for v in value.split(DELIMITER) if v]
|
||||
else:
|
||||
|
||||
@@ -118,6 +118,9 @@ class TaxRule(LoggedModel):
|
||||
)
|
||||
custom_rules = models.TextField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ('event', 'rate', 'id')
|
||||
|
||||
def allow_delete(self):
|
||||
from pretix.base.models.orders import OrderFee, OrderPosition
|
||||
|
||||
|
||||
@@ -721,13 +721,10 @@ class BoxOfficeProvider(BasePaymentProvider):
|
||||
return False
|
||||
|
||||
def payment_control_render(self, request, payment) -> str:
|
||||
template = None
|
||||
payment_info = None
|
||||
|
||||
if payment.info:
|
||||
payment_info = json.loads(payment.info)
|
||||
if payment_info['payment_type'] == "sumup":
|
||||
template = get_template('pretixcontrol/boxoffice/payment_sumup.html')
|
||||
if not payment.info:
|
||||
return
|
||||
payment_info = json.loads(payment.info)
|
||||
template = get_template('pretixcontrol/boxoffice/payment.html')
|
||||
|
||||
ctx = {
|
||||
'request': request,
|
||||
@@ -737,11 +734,7 @@ class BoxOfficeProvider(BasePaymentProvider):
|
||||
'payment': payment,
|
||||
'provider': self,
|
||||
}
|
||||
|
||||
if template:
|
||||
return template.render(ctx)
|
||||
else:
|
||||
return
|
||||
return template.render(ctx)
|
||||
|
||||
|
||||
class ManualPayment(BasePaymentProvider):
|
||||
|
||||
@@ -276,6 +276,10 @@ class CartManager:
|
||||
err = None
|
||||
changed_prices = {}
|
||||
for cp in expired:
|
||||
removed_positions = {op.position.pk for op in self._operations if isinstance(op, self.RemoveOperation)}
|
||||
if cp.pk in removed_positions or (cp.addon_to_id and cp.addon_to_id in removed_positions):
|
||||
continue
|
||||
|
||||
if cp.is_bundled:
|
||||
try:
|
||||
bundle = cp.addon_to.item.bundles.get(bundled_item=cp.item, bundled_variation=cp.variation)
|
||||
|
||||
@@ -120,7 +120,7 @@ def build_invoice(invoice: Invoice) -> Invoice:
|
||||
positions = list(
|
||||
invoice.order.positions.select_related('addon_to', 'item', 'tax_rule', 'subevent', 'variation').annotate(
|
||||
addon_c=Count('addons')
|
||||
)
|
||||
).order_by('positionid', 'id')
|
||||
)
|
||||
|
||||
reverse_charge = False
|
||||
|
||||
@@ -212,15 +212,21 @@ def mail_send_task(self, *args, to: List[str], subject: str, body: str, html: st
|
||||
order = None
|
||||
else:
|
||||
if attach_tickets:
|
||||
args = []
|
||||
attach_size = 0
|
||||
for name, ct in get_tickets_for_order(order):
|
||||
try:
|
||||
email.attach(
|
||||
name,
|
||||
ct.file.read(),
|
||||
ct.type
|
||||
)
|
||||
except:
|
||||
pass
|
||||
content = ct.file.read()
|
||||
args.append((name, content, ct.type))
|
||||
attach_size += len(content)
|
||||
|
||||
if attach_tickets < 4 * 1024 * 1024:
|
||||
# Do not attach more than 4MB, it will bounce way to often.
|
||||
|
||||
for a in args:
|
||||
try:
|
||||
email.attach(*a)
|
||||
except:
|
||||
pass
|
||||
|
||||
email = email_filter.send_chained(event, 'message', message=email, order=order)
|
||||
|
||||
|
||||
@@ -42,7 +42,9 @@ from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.services.pricing import get_price
|
||||
from pretix.base.services.tasks import ProfiledTask
|
||||
from pretix.base.signals import (
|
||||
allow_ticket_download, order_fee_calculation, order_placed, periodic_task,
|
||||
allow_ticket_download, order_approved, order_canceled, order_changed,
|
||||
order_denied, order_expired, order_fee_calculation, order_placed,
|
||||
periodic_task,
|
||||
)
|
||||
from pretix.celery_app import app
|
||||
from pretix.helpers.models import modelcopy
|
||||
@@ -134,55 +136,58 @@ def mark_order_refunded(order, user=None, auth=None, api_token=None):
|
||||
)
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def mark_order_expired(order, user=None, auth=None):
|
||||
"""
|
||||
Mark this order as expired. This sets the payment status and returns the order object.
|
||||
:param order: The order to change
|
||||
:param user: The user that performed the change
|
||||
"""
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
if isinstance(user, int):
|
||||
user = User.objects.get(pk=user)
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_EXPIRED
|
||||
order.save(update_fields=['status'])
|
||||
with transaction.atomic():
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
if isinstance(user, int):
|
||||
user = User.objects.get(pk=user)
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_EXPIRED
|
||||
order.save(update_fields=['status'])
|
||||
|
||||
order.log_action('pretix.event.order.expired', user=user, auth=auth)
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
order.log_action('pretix.event.order.expired', user=user, auth=auth)
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
|
||||
order_expired.send(order.event, order=order)
|
||||
return order
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def approve_order(order, user=None, send_mail: bool=True, auth=None):
|
||||
"""
|
||||
Mark this order as approved
|
||||
:param order: The order to change
|
||||
:param user: The user that performed the change
|
||||
"""
|
||||
if not order.require_approval or not order.status == Order.STATUS_PENDING:
|
||||
raise OrderError(_('This order is not pending approval.'))
|
||||
with transaction.atomic():
|
||||
if not order.require_approval or not order.status == Order.STATUS_PENDING:
|
||||
raise OrderError(_('This order is not pending approval.'))
|
||||
|
||||
order.require_approval = False
|
||||
order.set_expires(now(), order.event.subevents.filter(id__in=[p.subevent_id for p in order.positions.all()]))
|
||||
order.save(update_fields=['require_approval', 'expires'])
|
||||
order.require_approval = False
|
||||
order.set_expires(now(), order.event.subevents.filter(id__in=[p.subevent_id for p in order.positions.all()]))
|
||||
order.save(update_fields=['require_approval', 'expires'])
|
||||
|
||||
order.log_action('pretix.event.order.approved', user=user, auth=auth)
|
||||
if order.total == Decimal('0.00'):
|
||||
p = order.payments.create(
|
||||
state=OrderPayment.PAYMENT_STATE_CREATED,
|
||||
provider='free',
|
||||
amount=0,
|
||||
fee=None
|
||||
)
|
||||
try:
|
||||
p.confirm(send_mail=False, count_waitinglist=False, user=user, auth=auth)
|
||||
except Quota.QuotaExceededException:
|
||||
raise OrderError(error_messages['unavailable'])
|
||||
order.log_action('pretix.event.order.approved', user=user, auth=auth)
|
||||
if order.total == Decimal('0.00'):
|
||||
p = order.payments.create(
|
||||
state=OrderPayment.PAYMENT_STATE_CREATED,
|
||||
provider='free',
|
||||
amount=0,
|
||||
fee=None
|
||||
)
|
||||
try:
|
||||
p.confirm(send_mail=False, count_waitinglist=False, user=user, auth=auth)
|
||||
except Quota.QuotaExceededException:
|
||||
raise OrderError(error_messages['unavailable'])
|
||||
|
||||
order_approved.send(order.event, order=order)
|
||||
|
||||
invoice = order.invoices.last() # Might be generated by plugin already
|
||||
if order.event.settings.get('invoice_generate') == 'True' and invoice_qualified(order):
|
||||
@@ -234,30 +239,32 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None):
|
||||
return order.pk
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def deny_order(order, comment='', user=None, send_mail: bool=True, auth=None):
|
||||
"""
|
||||
Mark this order as canceled
|
||||
:param order: The order to change
|
||||
:param user: The user that performed the change
|
||||
"""
|
||||
if not order.require_approval or not order.status == Order.STATUS_PENDING:
|
||||
raise OrderError(_('This order is not pending approval.'))
|
||||
with transaction.atomic():
|
||||
if not order.require_approval or not order.status == Order.STATUS_PENDING:
|
||||
raise OrderError(_('This order is not pending approval.'))
|
||||
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_CANCELED
|
||||
order.save(update_fields=['status'])
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_CANCELED
|
||||
order.save(update_fields=['status'])
|
||||
|
||||
order.log_action('pretix.event.order.denied', user=user, auth=auth, data={
|
||||
'comment': comment
|
||||
})
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
order.log_action('pretix.event.order.denied', user=user, auth=auth, data={
|
||||
'comment': comment
|
||||
})
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
|
||||
for position in order.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
for position in order.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
|
||||
order_denied.send(order.event, order=order)
|
||||
|
||||
if send_mail:
|
||||
try:
|
||||
@@ -294,7 +301,6 @@ def deny_order(order, comment='', user=None, send_mail: bool=True, auth=None):
|
||||
return order.pk
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device=None, oauth_application=None,
|
||||
cancellation_fee=None):
|
||||
"""
|
||||
@@ -302,85 +308,87 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
:param order: The order to change
|
||||
:param user: The user that performed the change
|
||||
"""
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
if isinstance(user, int):
|
||||
user = User.objects.get(pk=user)
|
||||
if isinstance(api_token, int):
|
||||
api_token = TeamAPIToken.objects.get(pk=api_token)
|
||||
if isinstance(device, int):
|
||||
device = Device.objects.get(pk=device)
|
||||
if isinstance(oauth_application, int):
|
||||
oauth_application = OAuthApplication.objects.get(pk=oauth_application)
|
||||
if isinstance(cancellation_fee, str):
|
||||
cancellation_fee = Decimal(cancellation_fee)
|
||||
with transaction.atomic():
|
||||
if isinstance(order, int):
|
||||
order = Order.objects.get(pk=order)
|
||||
if isinstance(user, int):
|
||||
user = User.objects.get(pk=user)
|
||||
if isinstance(api_token, int):
|
||||
api_token = TeamAPIToken.objects.get(pk=api_token)
|
||||
if isinstance(device, int):
|
||||
device = Device.objects.get(pk=device)
|
||||
if isinstance(oauth_application, int):
|
||||
oauth_application = OAuthApplication.objects.get(pk=oauth_application)
|
||||
if isinstance(cancellation_fee, str):
|
||||
cancellation_fee = Decimal(cancellation_fee)
|
||||
|
||||
if not order.cancel_allowed():
|
||||
raise OrderError(_('You cannot cancel this order.'))
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
if not order.cancel_allowed():
|
||||
raise OrderError(_('You cannot cancel this order.'))
|
||||
i = order.invoices.filter(is_cancellation=False).last()
|
||||
if i:
|
||||
generate_cancellation(i)
|
||||
|
||||
if cancellation_fee:
|
||||
with order.event.lock():
|
||||
for position in order.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
position.canceled = True
|
||||
position.save(update_fields=['canceled'])
|
||||
for fee in order.fees.all():
|
||||
fee.canceled = True
|
||||
fee.save(update_fields=['canceled'])
|
||||
|
||||
f = OrderFee(
|
||||
fee_type=OrderFee.FEE_TYPE_CANCELLATION,
|
||||
value=cancellation_fee,
|
||||
tax_rule=order.event.settings.tax_rate_default,
|
||||
order=order,
|
||||
)
|
||||
f._calculate_tax()
|
||||
f.save()
|
||||
|
||||
if order.payment_refund_sum < cancellation_fee:
|
||||
raise OrderError(_('The cancellation fee cannot be higher than the payment credit of this order.'))
|
||||
order.status = Order.STATUS_PAID
|
||||
order.total = f.value
|
||||
order.save(update_fields=['status', 'total'])
|
||||
|
||||
if i:
|
||||
generate_invoice(order)
|
||||
else:
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_CANCELED
|
||||
order.save(update_fields=['status'])
|
||||
|
||||
if cancellation_fee:
|
||||
with order.event.lock():
|
||||
for position in order.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
position.canceled = True
|
||||
position.save(update_fields=['canceled'])
|
||||
for fee in order.fees.all():
|
||||
fee.canceled = True
|
||||
fee.save(update_fields=['canceled'])
|
||||
|
||||
f = OrderFee(
|
||||
fee_type=OrderFee.FEE_TYPE_CANCELLATION,
|
||||
value=cancellation_fee,
|
||||
tax_rule=order.event.settings.tax_rate_default,
|
||||
order=order,
|
||||
)
|
||||
f._calculate_tax()
|
||||
f.save()
|
||||
order.log_action('pretix.event.order.canceled', user=user, auth=api_token or oauth_application or device,
|
||||
data={'cancellation_fee': cancellation_fee})
|
||||
|
||||
if order.payment_refund_sum < cancellation_fee:
|
||||
raise OrderError(_('The cancellation fee cannot be higher than the payment credit of this order.'))
|
||||
order.status = Order.STATUS_PAID
|
||||
order.total = f.value
|
||||
order.save(update_fields=['status', 'total'])
|
||||
|
||||
if i:
|
||||
generate_invoice(order)
|
||||
else:
|
||||
with order.event.lock():
|
||||
order.status = Order.STATUS_CANCELED
|
||||
order.save(update_fields=['status'])
|
||||
|
||||
for position in order.positions.all():
|
||||
if position.voucher:
|
||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
||||
|
||||
order.log_action('pretix.event.order.canceled', user=user, auth=api_token or oauth_application or device,
|
||||
data={'cancellation_fee': cancellation_fee})
|
||||
|
||||
if send_mail:
|
||||
email_template = order.event.settings.mail_text_order_canceled
|
||||
email_context = {
|
||||
'event': order.event.name,
|
||||
'code': order.code,
|
||||
'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret
|
||||
})
|
||||
}
|
||||
with language(order.locale):
|
||||
email_subject = _('Order canceled: %(code)s') % {'code': order.code}
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_canceled', user
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent')
|
||||
if send_mail:
|
||||
email_template = order.event.settings.mail_text_order_canceled
|
||||
email_context = {
|
||||
'event': order.event.name,
|
||||
'code': order.code,
|
||||
'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={
|
||||
'order': order.code,
|
||||
'secret': order.secret
|
||||
})
|
||||
}
|
||||
with language(order.locale):
|
||||
email_subject = _('Order canceled: %(code)s') % {'code': order.code}
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_canceled', user
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent')
|
||||
|
||||
order_canceled.send(order.event, order=order)
|
||||
return order.pk
|
||||
|
||||
|
||||
@@ -1377,6 +1385,8 @@ class OrderChangeManager:
|
||||
if self.split_order:
|
||||
self._notify_user(self.split_order)
|
||||
|
||||
order_changed.send(self.order.event, order=self.order)
|
||||
|
||||
def _clear_tickets_cache(self):
|
||||
CachedTicket.objects.filter(order_position__order=self.order).delete()
|
||||
CachedCombinedTicket.objects.filter(order=self.order).delete()
|
||||
|
||||
@@ -49,6 +49,10 @@ DEFAULTS = {
|
||||
'default': 'True',
|
||||
'type': bool,
|
||||
},
|
||||
'invoice_address_not_asked_free': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
},
|
||||
'invoice_name_required': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
@@ -101,6 +105,10 @@ DEFAULTS = {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
},
|
||||
'presale_has_ended_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
},
|
||||
'payment_explanation': {
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
|
||||
@@ -275,6 +275,66 @@ because an already-paid order has been split.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_canceled = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order is canceled. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_expired = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order is marked as expired. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_modified = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order's information is modified. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_changed = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order's content is changed. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_approved = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order is being approved. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_denied = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
"""
|
||||
This signal is sent out every time an order is being denied. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
logentry_display = EventPluginSignal(
|
||||
providing_args=["logentry"]
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "error.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Bad Request" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-frown-o fa-fw big-icon"></i>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "error.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Permission denied" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-fw fa-lock big-icon"></i>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "error.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Not found" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-meh-o fa-fw big-icon"></i>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "error.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Internal Server Error" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-bolt big-icon fa-fw"></i>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "error.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% block title %}{% trans "Verification failed" %}{% endblock %}
|
||||
{% block content %}
|
||||
<i class="fa fa-frown-o big-icon fa-fw"></i>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% load compress %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
@@ -2,7 +2,7 @@ from django.utils import timezone
|
||||
from django.utils.translation.trans_real import DjangoTranslation
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.views.decorators.http import etag
|
||||
from django.views.i18n import JavaScriptCatalog, render_javascript_catalog
|
||||
from django.views.i18n import JavaScriptCatalog
|
||||
|
||||
# Yes, we want to regenerate this every time the module has been imported to
|
||||
# refresh the cache at least at every code deployment
|
||||
@@ -21,4 +21,5 @@ js_info_dict = {
|
||||
def js_catalog(request, lang):
|
||||
c = JavaScriptCatalog()
|
||||
c.translation = DjangoTranslation(lang, domain='djangojs')
|
||||
return render_javascript_catalog(c.get_catalog(), c.get_plural())
|
||||
context = c.get_context_data()
|
||||
return c.render_to_response(context)
|
||||
|
||||
@@ -20,10 +20,10 @@ def serve_metrics(request):
|
||||
return unauthed_response()
|
||||
|
||||
# check if the user is properly authorized:
|
||||
if "HTTP_AUTHORIZATION" not in request.META:
|
||||
if "Authorization" not in request.headers:
|
||||
return unauthed_response()
|
||||
|
||||
method, credentials = request.META["HTTP_AUTHORIZATION"].split(" ", 1)
|
||||
method, credentials = request.headers["Authorization"].split(" ", 1)
|
||||
if method.lower() != "basic":
|
||||
return unauthed_response()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
|
||||
from django import forms
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
@@ -186,25 +187,35 @@ class OrderQuestionsViewMixin(BaseQuestionsViewMixin):
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
return InvoiceAddress(order=self.order)
|
||||
|
||||
@cached_property
|
||||
def address_asked(self):
|
||||
return self.request.event.settings.invoice_address_asked and (
|
||||
self.order.total != Decimal('0.00') or not self.request.event.settings.invoice_address_not_asked_free
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def invoice_form(self):
|
||||
if not self.request.event.settings.invoice_address_asked and self.request.event.settings.invoice_name_required:
|
||||
if not self.address_asked and self.request.event.settings.invoice_name_required:
|
||||
return self.invoice_name_form_class(
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
instance=self.invoice_address, validate_vat_id=False,
|
||||
all_optional=self.all_optional
|
||||
)
|
||||
return self.invoice_form_class(
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
instance=self.invoice_address, validate_vat_id=False,
|
||||
all_optional=self.all_optional,
|
||||
)
|
||||
if self.address_asked:
|
||||
return self.invoice_form_class(
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
event=self.request.event,
|
||||
instance=self.invoice_address, validate_vat_id=False,
|
||||
all_optional=self.all_optional,
|
||||
)
|
||||
else:
|
||||
return forms.Form(data=self.request.POST if self.request.method == "POST" else None)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['order'] = self.order
|
||||
ctx['formgroups'] = self.formdict.items()
|
||||
ctx['invoice_form'] = self.invoice_form
|
||||
ctx['invoice_address_asked'] = self.address_asked
|
||||
return ctx
|
||||
|
||||
@@ -621,6 +621,10 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
widget=forms.CheckboxInput(attrs={'data-checkbox-dependency': '#id_invoice_address_asked'}),
|
||||
required=False
|
||||
)
|
||||
invoice_address_not_asked_free = forms.BooleanField(
|
||||
label=_('Do not ask for invoice address if an order is free'),
|
||||
required=False
|
||||
)
|
||||
invoice_include_free = forms.BooleanField(
|
||||
label=_("Show free products on invoices"),
|
||||
help_text=_("Note that invoices will never be generated for orders that contain only free "
|
||||
@@ -1049,6 +1053,14 @@ class DisplaySettingsForm(SettingsForm):
|
||||
required=False,
|
||||
widget=I18nTextarea
|
||||
)
|
||||
presale_has_ended_text = I18nFormField(
|
||||
label=_("End of presale text"),
|
||||
required=False,
|
||||
widget=I18nTextarea,
|
||||
widget_kwargs={'attrs': {'rows': '2'}},
|
||||
help_text=_("This text will be shown above the ticket shop once the designated sales timeframe for this event "
|
||||
"is over. You can use it to describe other options to get a ticket, such as a box office.")
|
||||
)
|
||||
voucher_explanation_text = I18nFormField(
|
||||
label=_("Voucher explanation"),
|
||||
required=False,
|
||||
|
||||
@@ -43,6 +43,7 @@ class QuestionForm(I18nModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['items'].queryset = self.instance.event.items.all()
|
||||
self.fields['items'].required = True
|
||||
self.fields['dependency_question'].queryset = self.instance.event.questions.filter(
|
||||
type__in=(Question.TYPE_BOOLEAN, Question.TYPE_CHOICE, Question.TYPE_CHOICE_MULTIPLE)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% load compress %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% if payment_info %}
|
||||
<dl class="dl-horizontal">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "Device ID" %}</dt>
|
||||
<dd>{{ payment_info.pos_id }}</dd>
|
||||
<dt>{% trans "Receipt ID" %}</dt>
|
||||
<dd>{{ payment_info.receipt_id }}</dd>
|
||||
{% if payment_info.payment_type == "sumup" %}
|
||||
<dt>{% trans "Payment provider" %}</dt>
|
||||
<dd>SumUp</dd>
|
||||
<dt>{% trans "Transaction Code" %}</dt>
|
||||
<dd>{{ payment_info.payment_data.tx_code}}</dd>
|
||||
<dd>{{ payment_info.payment_data.tx_code }}</dd>
|
||||
<dt>{% trans "Merchant Code" %}</dt>
|
||||
<dd>{{ payment_info.payment_data.merchant_code }}</dd>
|
||||
<dt>{% trans "Currency" %}</dt>
|
||||
@@ -17,6 +21,8 @@
|
||||
<dt>{% trans "Card Entry Mode" %}</dt>
|
||||
<dd>{{ payment_info.payment_data.entry_mode }}</dd>
|
||||
<dt>{% trans "Card number" %}</dt>
|
||||
<dd><i class="fa fa-cc-{{ payment_info.payment_data.card_type|lower }}"></i> **** **** **** {{ payment_info.payment_data.last4 }}</dd>
|
||||
</dl>
|
||||
{% endif %}
|
||||
<dd>
|
||||
<i class="fa fa-cc-{{ payment_info.payment_data.card_type|lower }}"></i> **** **** **** {{ payment_info.payment_data.last4 }}
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
@@ -11,6 +11,7 @@
|
||||
<legend>{% trans "Event page" %}</legend>
|
||||
{% bootstrap_field form.logo_image layout="control" %}
|
||||
{% bootstrap_field form.frontpage_text layout="control" %}
|
||||
{% bootstrap_field form.presale_has_ended_text layout="control" %}
|
||||
{% bootstrap_field form.voucher_explanation_text layout="control" %}
|
||||
{% bootstrap_field form.show_variations_expanded layout="control" %}
|
||||
{% bootstrap_field form.meta_noindex layout="control" %}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
{% bootstrap_field form.invoice_address_company_required layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_vatid layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_beneficiary layout="control" %}
|
||||
{% bootstrap_field form.invoice_address_not_asked_free layout="control" %}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{% trans "Your invoice details" %}</legend>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<form method="post" class="form-horizontal" href="" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="panel-group" id="questions_accordion">
|
||||
{% if request.event.settings.invoice_address_asked or order.invoice_address or request.event.settings.invoice_name_required %}
|
||||
{% if invoice_address_asked or order.invoice_address or request.event.settings.invoice_name_required %}
|
||||
<details class="panel panel-default" open>
|
||||
<summary class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load staticfiles %}
|
||||
{% load static %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "Connect to device:" %} {{ device.name }}</h1>
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
<strong>{% blocktrans %}Are you sure you want remove access for this device?{% endblocktrans %}</strong>
|
||||
{% trans "All data of this device will stay available, but you can't use the device any more." %}
|
||||
</p>
|
||||
<div class="alert alert-warning">
|
||||
<ul>
|
||||
<li>{% trans "All data uploaded by this device will stay available online." %}</li>
|
||||
<li>{% trans "If data (e.g. POS transactions or check-ins) has been created on this device and has not been uploaded, you will no longer be able to upload it." %}</li>
|
||||
<li>{% trans "If the device software supports it, personal data such as orders will be deleted from the device on the next synchronization attempt. Non-personal data such as event metadata and POS transactions will persist until you uninstall or reset the software manually." %}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-group submit-group">
|
||||
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}" class="btn btn-default btn-cancel">
|
||||
{% trans "Cancel" %}
|
||||
|
||||
@@ -18,8 +18,8 @@ from django.views.generic.edit import DeleteView
|
||||
|
||||
from pretix.base.forms import I18nFormSet
|
||||
from pretix.base.models import (
|
||||
CachedTicket, Item, ItemCategory, ItemVariation, Order, Question,
|
||||
QuestionAnswer, QuestionOption, Quota, Voucher,
|
||||
CachedTicket, CartPosition, Item, ItemCategory, ItemVariation, Order,
|
||||
Question, QuestionAnswer, QuestionOption, Quota, Voucher,
|
||||
)
|
||||
from pretix.base.models.event import SubEvent
|
||||
from pretix.base.models.items import ItemAddOn, ItemBundle
|
||||
@@ -49,7 +49,9 @@ class ItemList(ListView):
|
||||
event=self.request.event
|
||||
).annotate(
|
||||
var_count=Count('variations')
|
||||
).prefetch_related("category")
|
||||
).prefetch_related("category").order_by(
|
||||
'category__position', 'category', 'position'
|
||||
)
|
||||
|
||||
|
||||
def item_move(request, item, up=True):
|
||||
@@ -1158,6 +1160,7 @@ class ItemDelete(EventPermissionRequiredMixin, DeleteView):
|
||||
success_url = self.get_success_url()
|
||||
o = self.get_object()
|
||||
if o.allow_delete():
|
||||
CartPosition.objects.filter(addon_to__item=self.get_object()).delete()
|
||||
self.get_object().cartposition_set.all().delete()
|
||||
self.get_object().log_action('pretix.event.item.deleted', user=self.request.user)
|
||||
self.get_object().delete()
|
||||
|
||||
@@ -57,7 +57,7 @@ from pretix.base.services.orders import (
|
||||
from pretix.base.services.stats import order_overview
|
||||
from pretix.base.services.tickets import generate
|
||||
from pretix.base.signals import (
|
||||
register_data_exporters, register_ticket_outputs,
|
||||
order_modified, register_data_exporters, register_ticket_outputs,
|
||||
)
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||
@@ -1305,7 +1305,8 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView):
|
||||
messages.error(self.request,
|
||||
_("We had difficulties processing your input. Please review the errors below."))
|
||||
return self.get(request, *args, **kwargs)
|
||||
self.invoice_form.save()
|
||||
if hasattr(self.invoice_form, 'save'):
|
||||
self.invoice_form.save()
|
||||
self.order.log_action('pretix.event.order.modified', {
|
||||
'invoice_data': self.invoice_form.cleaned_data,
|
||||
'data': [{
|
||||
@@ -1320,6 +1321,8 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView):
|
||||
|
||||
CachedTicket.objects.filter(order_position__order=self.order).delete()
|
||||
CachedCombinedTicket.objects.filter(order=self.order).delete()
|
||||
|
||||
order_modified.send(sender=self.request.event, order=self.order)
|
||||
return redirect(self.get_order_url())
|
||||
|
||||
|
||||
|
||||
@@ -756,7 +756,7 @@ class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.object.api_token = None
|
||||
self.object.revoked = True
|
||||
self.object.save()
|
||||
self.object.log_action('pretix.device.revoked', user=self.request.user)
|
||||
messages.success(request, _('Access for this device has been revoked.'))
|
||||
|
||||
@@ -16,6 +16,7 @@ from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
from django.views import View
|
||||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
|
||||
from pretix.base.models import CartPosition
|
||||
from pretix.base.models.checkin import CheckinList
|
||||
from pretix.base.models.event import SubEvent, SubEventMetaValue
|
||||
from pretix.base.models.items import (
|
||||
@@ -117,6 +118,7 @@ class SubEventDelete(EventPermissionRequiredMixin, DeleteView):
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
else:
|
||||
self.object.log_action('pretix.subevent.deleted', user=self.request.user)
|
||||
CartPosition.objects.filter(addon_to__subevent=self.object).delete()
|
||||
self.object.cartposition_set.all().delete()
|
||||
self.object.delete()
|
||||
messages.success(request, pgettext_lazy('subevent', 'The selected date has been deleted.'))
|
||||
@@ -512,6 +514,7 @@ class SubEventBulkAction(EventPermissionRequiredMixin, View):
|
||||
elif request.POST.get('action') == 'delete_confirm':
|
||||
for obj in self.objects:
|
||||
if obj.allow_delete():
|
||||
CartPosition.objects.filter(addon_to__subevent=obj).delete()
|
||||
obj.cartposition_set.all().delete()
|
||||
obj.log_action('pretix.subevent.deleted', user=self.request.user)
|
||||
obj.delete()
|
||||
|
||||
@@ -17,7 +17,7 @@ from django.views.generic import (
|
||||
CreateView, DeleteView, ListView, TemplateView, UpdateView, View,
|
||||
)
|
||||
|
||||
from pretix.base.models import LogEntry, Voucher
|
||||
from pretix.base.models import CartPosition, LogEntry, OrderPosition, Voucher
|
||||
from pretix.base.models.vouchers import _generate_random_code
|
||||
from pretix.control.forms.filter import VoucherFilterForm
|
||||
from pretix.control.forms.vouchers import VoucherBulkForm, VoucherForm
|
||||
@@ -143,6 +143,7 @@ class VoucherDelete(EventPermissionRequiredMixin, DeleteView):
|
||||
messages.error(request, _('A voucher can not be deleted if it already has been redeemed.'))
|
||||
else:
|
||||
self.object.log_action('pretix.voucher.deleted', user=self.request.user)
|
||||
CartPosition.objects.filter(addon_to__voucher=False).delete()
|
||||
self.object.cartposition_set.all().delete()
|
||||
self.object.delete()
|
||||
messages.success(request, _('The selected voucher has been deleted.'))
|
||||
@@ -348,6 +349,7 @@ class VoucherBulkAction(EventPermissionRequiredMixin, View):
|
||||
for obj in self.objects:
|
||||
if obj.allow_delete():
|
||||
obj.log_action('pretix.voucher.deleted', user=self.request.user)
|
||||
OrderPosition.objects.filter(addon_to__voucher=obj).delete()
|
||||
obj.cartposition_set.all().delete()
|
||||
obj.delete()
|
||||
else:
|
||||
|
||||
@@ -13,7 +13,7 @@ class SessionReauthRequired(Exception):
|
||||
|
||||
|
||||
def get_user_agent_hash(request):
|
||||
return hashlib.sha256(request.META['HTTP_USER_AGENT'].encode()).hexdigest()
|
||||
return hashlib.sha256(request.headers['User-Agent'].encode()).hexdigest()
|
||||
|
||||
|
||||
def assert_session_valid(request):
|
||||
@@ -26,7 +26,7 @@ def assert_session_valid(request):
|
||||
if time.time() - last_used > settings.PRETIX_SESSION_TIMEOUT_RELATIVE:
|
||||
raise SessionReauthRequired()
|
||||
|
||||
if 'HTTP_USER_AGENT' in request.META:
|
||||
if 'User-Agent' in request.headers:
|
||||
if 'pinned_user_agent' in request.session:
|
||||
if request.session.get('pinned_user_agent') != get_user_agent_hash(request):
|
||||
raise SessionInvalid()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
||||
16104
src/pretix/locale/ca/LC_MESSAGES/django.po
Normal file
16104
src/pretix/locale/ca/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
465
src/pretix/locale/ca/LC_MESSAGES/djangojs.po
Normal file
465
src/pretix/locale/ca/LC_MESSAGES/djangojs.po
Normal file
@@ -0,0 +1,465 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ca\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"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:68
|
||||
msgid "Marked as paid"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:76
|
||||
msgid "Comment:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Placed orders"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Paid orders"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
msgid "Total revenue"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
|
||||
msgid "Contacting Stripe …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:56
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:39
|
||||
#: pretix/static/pretixbase/js/asynctask.js:95
|
||||
msgid ""
|
||||
"Your request has been queued on the server and will now be processed. "
|
||||
"Depending on the size of your event, this might take up to a few minutes."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:45
|
||||
#: pretix/static/pretixbase/js/asynctask.js:101
|
||||
msgid ""
|
||||
"Your request arrived on the server but we still wait for it to be processed. "
|
||||
"If this takes longer than two minutes, please contact us or go back in your "
|
||||
"browser and try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:66
|
||||
#: pretix/static/pretixbase/js/asynctask.js:124
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:23
|
||||
msgid "An error of type {code} occurred."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:69
|
||||
msgid ""
|
||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||
"{code}"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:115
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:20
|
||||
msgid "The request took to long. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:127
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:25
|
||||
msgid ""
|
||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:148
|
||||
msgid "We are processing your request …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:156
|
||||
msgid ""
|
||||
"We are currently sending your request to the server. If this takes longer "
|
||||
"than one minute, please check your internet connection and then reload this "
|
||||
"page and try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:193
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:20
|
||||
msgid "Close message"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/clipboard.js:23
|
||||
msgid "Copied!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/clipboard.js:29
|
||||
msgid "Press Ctrl-C to copy!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:43
|
||||
msgid "Lead Scan QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:45
|
||||
msgid "Check-in QR"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:249
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:418
|
||||
msgid "Group of objects"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:424
|
||||
msgid "Text object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:426
|
||||
msgid "Barcode area"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:428
|
||||
msgid "Powered by pretix"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:430
|
||||
msgid "Object"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:434
|
||||
msgid "Ticket design"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:687
|
||||
msgid "Saving failed."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:735
|
||||
msgid "Do you really want to leave the editor without saving your changes?"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:749
|
||||
msgid "Error while uploading your PDF file, please try again."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:18
|
||||
msgid "An error has occurred."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:52
|
||||
msgid "Generating messages …"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:55
|
||||
msgid "Unknown error."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:217
|
||||
msgid "Your color has great contrast and is very easy to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:221
|
||||
msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:225
|
||||
msgid ""
|
||||
"Your color has bad contrast for text on white background, please choose a "
|
||||
"darker shade."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:306
|
||||
msgid "All"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:307
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:595
|
||||
msgid "Use a different name internally"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:646
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:42
|
||||
msgid "Others"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:71
|
||||
msgid "Count"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:121
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:39
|
||||
msgid "The items in your cart are no longer reserved for you."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:41
|
||||
msgid "Cart expired"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:46
|
||||
msgid "The items in your cart are reserved for you for one minute."
|
||||
msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:14
|
||||
msgctxt "widget"
|
||||
msgid "Sold out"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:15
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:16
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "FREE"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "from %(currency)s %(price)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
msgctxt "widget"
|
||||
msgid "incl. %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
msgid "The ticket shop could not be loaded."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "The cart could not be created. Please try again later"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
msgid "Waiting list"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
"products, they will be added to your existing cart."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:32
|
||||
msgctxt "widget"
|
||||
msgid "Resume checkout"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:33
|
||||
msgctxt "widget"
|
||||
msgid ""
|
||||
"<a href=\"https://pretix.eu\" target=\"_blank\" rel=\"noopener\">event "
|
||||
"ticketing powered by pretix</a>"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
msgid "Redeem"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:37
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
msgctxt "widget"
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
msgctxt "widget"
|
||||
msgid "See variations"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2018-04-24 14:22+0000\n"
|
||||
"Last-Translator: Pernille Thorsen <perth@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-22 15:00+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-22 15:00+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"PO-Revision-Date: 2019-02-20 03:00+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-31 08:00+0000\n"
|
||||
"Last-Translator: oocf <oswaldocerna@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
"js/es/>\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 3.4\n"
|
||||
"X-Generator: Weblate 3.5.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -220,7 +220,7 @@ msgstr "Usar un nombre diferente internamente"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:646
|
||||
msgid "Click to close"
|
||||
msgstr ""
|
||||
msgstr "Click para cerrar"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:42
|
||||
msgid "Others"
|
||||
@@ -232,13 +232,11 @@ msgstr "Cantidad"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Si"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:121
|
||||
#, fuzzy
|
||||
#| msgid "None"
|
||||
msgid "No"
|
||||
msgstr "Ninguno"
|
||||
msgstr "No"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
msgid "(one more date)"
|
||||
@@ -300,12 +298,12 @@ msgstr "más %(rate)s% %(taxname)s"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
msgstr "incl. impuestos"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
msgstr "más impuestos"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
@@ -400,102 +398,100 @@ msgid "See variations"
|
||||
msgstr "Ver variaciones"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#, fuzzy
|
||||
#| msgid "Use a different name internally"
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Usar un nombre diferente internamente"
|
||||
msgstr "Elige un evento diferente"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "Atrás"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
msgstr "Siguiente mes"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
msgstr "Mes anterior"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
msgstr "Me"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
msgstr "Ma"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
msgstr "Mie"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
msgstr "Ju"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
msgstr "Vi"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
msgstr "Sá"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
msgstr "Do"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
msgstr "Enero"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
msgstr "Febrero"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
msgstr "Marzo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
msgstr "Abril"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
msgstr "Mayo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
msgstr "Junio"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
msgstr "Julio"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
msgstr "Agosto"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
msgstr "Septiembre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
msgstr "Octubre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
msgstr "Noviembre"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
msgstr "Diciembre"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Your request has been queued on the server and will now be processed. If "
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: French\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2018-10-28 10:23+0000\n"
|
||||
"Last-Translator: Arnaud Vergnet <keplyx@gmail.com>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-01-02 08:20+0000\n"
|
||||
"Last-Translator: amefad <fame@libero.it>\n"
|
||||
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"PO-Revision-Date: 2019-03-13 15:49+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-24 05:00+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"nl/>\n"
|
||||
@@ -16,7 +16,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 3.4\n"
|
||||
"X-Generator: Weblate 3.5.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -40,7 +40,7 @@ msgstr "Betaalde bestellingen"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
msgid "Total revenue"
|
||||
msgstr "Volledige omzet"
|
||||
msgstr "Totaalomzet"
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
|
||||
msgid "Contacting Stripe …"
|
||||
@@ -226,13 +226,11 @@ msgstr "Aantal"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Ja"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:121
|
||||
#, fuzzy
|
||||
#| msgid "None"
|
||||
msgid "No"
|
||||
msgstr "Geen"
|
||||
msgstr "Nee"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
msgid "(one more date)"
|
||||
@@ -294,12 +292,12 @@ msgstr "plus %(rate)s% %(taxname)s"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
msgstr "incl. belasting"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
msgstr "excl. belasting"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
@@ -394,102 +392,100 @@ msgid "See variations"
|
||||
msgstr "Zie variaties"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#, fuzzy
|
||||
#| msgid "Use a different name internally"
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Gebruik intern een andere naam"
|
||||
msgstr "Ander evenement kiezen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "Terug"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
msgstr "Volgende maand"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
msgstr "Vorige maand"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
msgstr "Ma"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
msgstr "Di"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
msgstr "Wo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
msgstr "Do"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
msgstr "Vr"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
msgstr "Za"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
msgstr "Zo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
msgstr "Januari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
msgstr "Februari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
msgstr "Maart"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
msgstr "April"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
msgstr "Mei"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
msgstr "Juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
msgstr "Juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
msgstr "Augustus"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
msgstr "September"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
msgstr "Oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
msgstr "November"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
msgstr "December"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Your request has been queued on the server and will now be processed. If "
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"PO-Revision-Date: 2019-03-13 15:49+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-27 01:00+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix-js/nl_Informal/>\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 3.4\n"
|
||||
"X-Generator: Weblate 3.5.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -41,7 +41,7 @@ msgstr "Betaalde bestellingen"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
msgid "Total revenue"
|
||||
msgstr "Volledige omzet"
|
||||
msgstr "Totaalomzet"
|
||||
|
||||
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
|
||||
msgid "Contacting Stripe …"
|
||||
@@ -228,13 +228,11 @@ msgstr "Aantal"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Ja"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:121
|
||||
#, fuzzy
|
||||
#| msgid "None"
|
||||
msgid "No"
|
||||
msgstr "Geen"
|
||||
msgstr "Nee"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
msgid "(one more date)"
|
||||
@@ -296,12 +294,12 @@ msgstr "plus %(rate)s% %(taxname)s"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
msgstr "incl. belasting"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
msgstr "excl. belasting"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
@@ -396,99 +394,97 @@ msgid "See variations"
|
||||
msgstr "Zie variaties"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#, fuzzy
|
||||
#| msgid "Use a different name internally"
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "Gebruik intern een andere naam"
|
||||
msgstr "Ander evenement kiezen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "Terug"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
msgstr "Volgende maand"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
msgstr "Vorige maand"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
msgstr "Ma"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
msgstr "Di"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
msgstr "Wo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
msgstr "Do"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
msgstr "Vr"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
msgstr "Za"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
msgstr "Zo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
msgstr "Januari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
msgstr "Februari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
msgstr "Maart"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
msgstr "April"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
msgstr "Mei"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
msgstr "Juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
msgstr "Juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
msgstr "Augustus"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
msgstr "September"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
msgstr "Oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
msgstr "November"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
msgstr "December"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-15 11:19+0000\n"
|
||||
"Last-Translator: Serge Bazanski <q3k@hackerspace.pl>\n"
|
||||
"Language-Team: Polish <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-19 09:00+0000\n"
|
||||
"Last-Translator: Vitor Reis <vitor.reis7@gmail.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://translate.pretix.eu/projects/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-01-02 08:21+0000\n"
|
||||
"Last-Translator: Alexey Zh <write2aracon@gmail.com>\n"
|
||||
"Language-Team: Russian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2018-09-03 06:36+0000\n"
|
||||
"Last-Translator: Yunus Fırat Pişkin <firat.piskin@idvlabs.com>\n"
|
||||
"Language-Team: Turkish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-22 14:50+0000\n"
|
||||
"PO-Revision-Date: 2019-03-19 09:00+0000\n"
|
||||
"POT-Creation-Date: 2019-04-03 13:19+0000\n"
|
||||
"PO-Revision-Date: 2019-03-28 14:00+0000\n"
|
||||
"Last-Translator: yichengsd <sunzl@jxepub.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix-js/zh_Hans/>\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 3.4\n"
|
||||
"X-Generator: Weblate 3.5.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -219,13 +219,11 @@ msgstr "数量"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:120
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "是"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:121
|
||||
#, fuzzy
|
||||
#| msgid "None"
|
||||
msgid "No"
|
||||
msgstr "无"
|
||||
msgstr "否"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:108
|
||||
msgid "(one more date)"
|
||||
@@ -283,12 +281,12 @@ msgstr "另加 %(rate)s% %(taxname)s"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "incl. taxes"
|
||||
msgstr ""
|
||||
msgstr "包含税"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr ""
|
||||
msgstr "税"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
@@ -381,102 +379,100 @@ msgid "See variations"
|
||||
msgstr "查看变化"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
#, fuzzy
|
||||
#| msgid "Use a different name internally"
|
||||
msgctxt "widget"
|
||||
msgid "Choose a different event"
|
||||
msgstr "在内部使用一个不同的名称"
|
||||
msgstr "选择一个不同的活动"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
msgstr "后退"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
msgctxt "widget"
|
||||
msgid "Next month"
|
||||
msgstr ""
|
||||
msgstr "下个月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
msgctxt "widget"
|
||||
msgid "Previous month"
|
||||
msgstr ""
|
||||
msgstr "上个月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgid "Mo"
|
||||
msgstr ""
|
||||
msgstr "周一"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:47
|
||||
msgid "Tu"
|
||||
msgstr ""
|
||||
msgstr "周二"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:48
|
||||
msgid "We"
|
||||
msgstr ""
|
||||
msgstr "周三"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgid "Th"
|
||||
msgstr ""
|
||||
msgstr "周四"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
msgid "Fr"
|
||||
msgstr ""
|
||||
msgstr "周五"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgid "Sa"
|
||||
msgstr ""
|
||||
msgstr "周六"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:52
|
||||
msgid "Su"
|
||||
msgstr ""
|
||||
msgstr "周天"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:55
|
||||
msgid "January"
|
||||
msgstr ""
|
||||
msgstr "一月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:56
|
||||
msgid "February"
|
||||
msgstr ""
|
||||
msgstr "二月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgid "March"
|
||||
msgstr ""
|
||||
msgstr "三月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgid "April"
|
||||
msgstr ""
|
||||
msgstr "四月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgid "May"
|
||||
msgstr ""
|
||||
msgstr "五月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgid "June"
|
||||
msgstr ""
|
||||
msgstr "六月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgid "July"
|
||||
msgstr ""
|
||||
msgstr "七月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
msgid "August"
|
||||
msgstr ""
|
||||
msgstr "八月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgid "September"
|
||||
msgstr ""
|
||||
msgstr "九月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgid "October"
|
||||
msgstr ""
|
||||
msgstr "十月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
msgid "November"
|
||||
msgstr ""
|
||||
msgstr "十一月"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
msgid "December"
|
||||
msgstr ""
|
||||
msgstr "十二月"
|
||||
|
||||
#~ msgid "Ja"
|
||||
#~ msgstr "是"
|
||||
|
||||
@@ -23,10 +23,10 @@ LOCAL_HOST_NAMES = ('testserver', 'localhost')
|
||||
class MultiDomainMiddleware(MiddlewareMixin):
|
||||
def process_request(self, request):
|
||||
# We try three options, in order of decreasing preference.
|
||||
if settings.USE_X_FORWARDED_HOST and ('HTTP_X_FORWARDED_HOST' in request.META):
|
||||
host = request.META['HTTP_X_FORWARDED_HOST']
|
||||
elif 'HTTP_HOST' in request.META:
|
||||
host = request.META['HTTP_HOST']
|
||||
if settings.USE_X_FORWARDED_HOST and ('X-Forwarded-Host' in request.headers):
|
||||
host = request.headers['X-Forwarded-Host']
|
||||
elif 'Host' in request.headers:
|
||||
host = request.headers['Host']
|
||||
else:
|
||||
# Reconstruct the host using the algorithm from PEP 333.
|
||||
host = request.META['SERVER_NAME']
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user