mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Use new permissions, remove inconsistencies
This commit is contained in:
@@ -30,7 +30,7 @@ software_brand string Device software
|
|||||||
software_version string Device software version (read-only)
|
software_version string Device software version (read-only)
|
||||||
created datetime Creation time
|
created datetime Creation time
|
||||||
initialized datetime Time of initialization (or ``null``)
|
initialized datetime Time of initialization (or ``null``)
|
||||||
initialization_token string Token for initialization
|
initialization_token string Token for initialization (field invisible without without write permission)
|
||||||
revoked boolean Whether this device no longer has access
|
revoked boolean Whether this device no longer has access
|
||||||
security_profile string The name of a supported security profile restricting API access
|
security_profile string The name of a supported security profile restricting API access
|
||||||
===================================== ========================== =======================================================
|
===================================== ========================== =======================================================
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ Endpoints
|
|||||||
|
|
||||||
Returns a list of all events within a given organizer the authenticated user/token has access to.
|
Returns a list of all events within a given organizer the authenticated user/token has access to.
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -161,8 +159,6 @@ Endpoints
|
|||||||
|
|
||||||
Returns information on one event, identified by its slug.
|
Returns information on one event, identified by its slug.
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -234,8 +230,6 @@ Endpoints
|
|||||||
Please note that events cannot be created as 'live' using this endpoint. Quotas and payment must be added to the
|
Please note that events cannot be created as 'live' using this endpoint. Quotas and payment must be added to the
|
||||||
event before sales can go live.
|
event before sales can go live.
|
||||||
|
|
||||||
Permission required: "Can create events"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -338,8 +332,6 @@ Endpoints
|
|||||||
Please note that you can only copy from events under the same organizer this way. Use the ``clone_from`` parameter
|
Please note that you can only copy from events under the same organizer this way. Use the ``clone_from`` parameter
|
||||||
when creating a new event for this instead.
|
when creating a new event for this instead.
|
||||||
|
|
||||||
Permission required: "Can create events"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -433,8 +425,6 @@ Endpoints
|
|||||||
|
|
||||||
Updates an event
|
Updates an event
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -510,8 +500,6 @@ Endpoints
|
|||||||
|
|
||||||
Delete an event. Note that events with orders cannot be deleted to ensure data integrity.
|
Delete an event. Note that events with orders cannot be deleted to ensure data integrity.
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -561,8 +549,6 @@ organizer level.
|
|||||||
|
|
||||||
Get current values of event settings.
|
Get current values of event settings.
|
||||||
|
|
||||||
Permission required: "Can change event settings" (Exception: with device auth, *some* settings can always be *read*.)
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -615,6 +601,8 @@ organizer level.
|
|||||||
|
|
||||||
Updates event settings. Note that ``PUT`` is not allowed here, only ``PATCH``.
|
Updates event settings. Note that ``PUT`` is not allowed here, only ``PATCH``.
|
||||||
|
|
||||||
|
Permission "Can change event settings" is always required. Some keys requrie additional permissions.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Settings can be stored at different levels in pretix. If a value is not set on event level, a default setting
|
Settings can be stored at different levels in pretix. If a value is not set on event level, a default setting
|
||||||
|
|||||||
@@ -110,8 +110,6 @@ Endpoints
|
|||||||
|
|
||||||
Updates an organizer. Currently only the ``plugins`` field may be updated.
|
Updates an organizer. Currently only the ``plugins`` field may be updated.
|
||||||
|
|
||||||
Permission required: "Can change organizer settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -172,8 +170,6 @@ information about the properties.
|
|||||||
|
|
||||||
Get current values of organizer settings.
|
Get current values of organizer settings.
|
||||||
|
|
||||||
Permission required: "Can change organizer settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ Endpoints
|
|||||||
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/lookup/
|
.. http:post:: /api/v1/organizers/(organizer)/reusablemedia/lookup/
|
||||||
|
|
||||||
Look up a new reusable medium by its identifier. In some cases, this might lead to the automatic creation of a new
|
Look up a new reusable medium by its identifier. In some cases, this might lead to the automatic creation of a new
|
||||||
medium behind the scenes.
|
medium behind the scenes, therefore this endpoint requires write permissions.
|
||||||
|
|
||||||
This endpoint, and this endpoint only, might return media from a different organizer if there is a cross-acceptance
|
This endpoint, and this endpoint only, might return media from a different organizer if there is a cross-acceptance
|
||||||
agreement. In this case, only linked gift cards will be returned, no order position or customer records,
|
agreement. In this case, only linked gift cards will be returned, no order position or customer records,
|
||||||
|
|||||||
@@ -154,8 +154,6 @@ Endpoints
|
|||||||
|
|
||||||
Creates a new subevent.
|
Creates a new subevent.
|
||||||
|
|
||||||
Permission required: "Can create events"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -300,8 +298,6 @@ Endpoints
|
|||||||
provide all fields of the resource, other fields will be reset to default. With ``PATCH``, you only need to provide
|
provide all fields of the resource, other fields will be reset to default. With ``PATCH``, you only need to provide
|
||||||
the fields that you want to change.
|
the fields that you want to change.
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
@@ -373,8 +369,6 @@ Endpoints
|
|||||||
|
|
||||||
Delete a sub-event. Note that events with orders cannot be deleted to ensure data integrity.
|
Delete a sub-event. Note that events with orders cannot be deleted to ensure data integrity.
|
||||||
|
|
||||||
Permission required: "Can change event settings"
|
|
||||||
|
|
||||||
**Example request**:
|
**Example request**:
|
||||||
|
|
||||||
.. sourcecode:: http
|
.. sourcecode:: http
|
||||||
|
|||||||
@@ -63,8 +63,6 @@ Possible values for ``limit_event_permissions`` defined in the core pretix syste
|
|||||||
|
|
||||||
event.settings.general:write
|
event.settings.general:write
|
||||||
event.settings.payment:write
|
event.settings.payment:write
|
||||||
event.settings.plugins:write
|
|
||||||
event.settings.email.sender:write
|
|
||||||
event.settings.tax:write
|
event.settings.tax:write
|
||||||
event.settings.invoicing:write
|
event.settings.invoicing:write
|
||||||
event.subevents:write
|
event.subevents:write
|
||||||
|
|||||||
@@ -707,7 +707,10 @@ class TaxRuleSerializer(CountryFieldMixin, I18nAwareModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class EventSettingsSerializer(SettingsSerializer):
|
class EventSettingsSerializer(SettingsSerializer):
|
||||||
|
default_write_permission = 'event.settings.general:write'
|
||||||
default_fields = [
|
default_fields = [
|
||||||
|
# These are readable for all users with access to the events, therefore secrets made in the settings store
|
||||||
|
# should not be included!
|
||||||
'imprint_url',
|
'imprint_url',
|
||||||
'checkout_email_helptext',
|
'checkout_email_helptext',
|
||||||
'presale_has_ended_text',
|
'presale_has_ended_text',
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from decimal import Decimal
|
|||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import PermissionDenied, ValidationError
|
||||||
|
|
||||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||||
from pretix.api.serializers.order import OrderPositionSerializer
|
from pretix.api.serializers.order import OrderPositionSerializer
|
||||||
@@ -66,6 +66,9 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if 'linked_giftcard' in self.context['request'].query_params.getlist('expand'):
|
if 'linked_giftcard' in self.context['request'].query_params.getlist('expand'):
|
||||||
|
if not self.context["can_read_giftcards"]:
|
||||||
|
raise PermissionDenied("No permission to access gift card details.")
|
||||||
|
|
||||||
self.fields['linked_giftcard'] = NestedGiftCardSerializer(read_only=True, context=self.context)
|
self.fields['linked_giftcard'] = NestedGiftCardSerializer(read_only=True, context=self.context)
|
||||||
if 'linked_giftcard.owner_ticket' in self.context['request'].query_params.getlist('expand'):
|
if 'linked_giftcard.owner_ticket' in self.context['request'].query_params.getlist('expand'):
|
||||||
self.fields['linked_giftcard'].fields['owner_ticket'] = NestedOrderPositionSerializer(read_only=True, context=self.context)
|
self.fields['linked_giftcard'].fields['owner_ticket'] = NestedOrderPositionSerializer(read_only=True, context=self.context)
|
||||||
@@ -77,6 +80,8 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if 'linked_orderposition' in self.context['request'].query_params.getlist('expand'):
|
if 'linked_orderposition' in self.context['request'].query_params.getlist('expand'):
|
||||||
|
# No additional permission check performed, documented limitation of the permission system
|
||||||
|
# Would get to complex/unusable otherwise since the permission depends on the event
|
||||||
self.fields['linked_orderposition'] = NestedOrderPositionSerializer(read_only=True)
|
self.fields['linked_orderposition'] = NestedOrderPositionSerializer(read_only=True)
|
||||||
else:
|
else:
|
||||||
self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField(
|
self.fields['linked_orderposition'] = serializers.PrimaryKeyRelatedField(
|
||||||
@@ -86,6 +91,9 @@ class ReusableMediaSerializer(I18nAwareModelSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if 'customer' in self.context['request'].query_params.getlist('expand'):
|
if 'customer' in self.context['request'].query_params.getlist('expand'):
|
||||||
|
if not self.context["can_read_customers"]:
|
||||||
|
raise PermissionDenied("No permission to access customer details.")
|
||||||
|
|
||||||
self.fields['customer'] = CustomerSerializer(read_only=True)
|
self.fields['customer'] = CustomerSerializer(read_only=True)
|
||||||
else:
|
else:
|
||||||
self.fields['customer'] = serializers.SlugRelatedField(
|
self.fields['customer'] = serializers.SlugRelatedField(
|
||||||
|
|||||||
@@ -422,7 +422,7 @@ class DeviceSerializer(serializers.ModelSerializer):
|
|||||||
created = serializers.DateTimeField(read_only=True)
|
created = serializers.DateTimeField(read_only=True)
|
||||||
revoked = serializers.BooleanField(read_only=True)
|
revoked = serializers.BooleanField(read_only=True)
|
||||||
initialized = serializers.DateTimeField(read_only=True)
|
initialized = serializers.DateTimeField(read_only=True)
|
||||||
initialization_token = serializers.DateTimeField(read_only=True)
|
initialization_token = serializers.CharField(read_only=True)
|
||||||
security_profile = serializers.ChoiceField(choices=[], required=False, default="full")
|
security_profile = serializers.ChoiceField(choices=[], required=False, default="full")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -436,6 +436,8 @@ class DeviceSerializer(serializers.ModelSerializer):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields['security_profile'].choices = [(k, v.verbose_name) for k, v in get_all_security_profiles().items()]
|
self.fields['security_profile'].choices = [(k, v.verbose_name) for k, v in get_all_security_profiles().items()]
|
||||||
|
if not self.context['can_see_tokens']:
|
||||||
|
del self.fields['initialization_token']
|
||||||
|
|
||||||
|
|
||||||
class TeamInviteSerializer(serializers.ModelSerializer):
|
class TeamInviteSerializer(serializers.ModelSerializer):
|
||||||
@@ -520,7 +522,10 @@ class TeamMemberSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class OrganizerSettingsSerializer(SettingsSerializer):
|
class OrganizerSettingsSerializer(SettingsSerializer):
|
||||||
|
default_write_permission = 'organizer.settings.general:write'
|
||||||
default_fields = [
|
default_fields = [
|
||||||
|
# These are readable for all users with access to the events, therefore secrets made in the settings store
|
||||||
|
# should not be included!
|
||||||
'customer_accounts',
|
'customer_accounts',
|
||||||
'customer_accounts_native',
|
'customer_accounts_native',
|
||||||
'customer_accounts_link_by_email',
|
'customer_accounts_link_by_email',
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ logger = logging.getLogger(__name__)
|
|||||||
class SettingsSerializer(serializers.Serializer):
|
class SettingsSerializer(serializers.Serializer):
|
||||||
default_fields = []
|
default_fields = []
|
||||||
readonly_fields = []
|
readonly_fields = []
|
||||||
|
default_write_permission = 'organizer.settings.general:write'
|
||||||
|
write_permission_required = {}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.changed_data = []
|
self.changed_data = []
|
||||||
@@ -58,9 +60,17 @@ class SettingsSerializer(serializers.Serializer):
|
|||||||
f._label = str(form_kwargs.get('label', fname))
|
f._label = str(form_kwargs.get('label', fname))
|
||||||
f._help_text = str(form_kwargs.get('help_text'))
|
f._help_text = str(form_kwargs.get('help_text'))
|
||||||
f.parent = self
|
f.parent = self
|
||||||
|
|
||||||
|
self.write_permission_required[fname] = DEFAULTS[fname].get('write_permission', self.default_write_permission)
|
||||||
|
|
||||||
self.fields[fname] = f
|
self.fields[fname] = f
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
for k in attrs.keys():
|
||||||
|
p = self.write_permission_required.get(k, self.default_write_permission)
|
||||||
|
if p not in self.context["permissions"]:
|
||||||
|
raise ValidationError({k: f"Setting this field requires permission {p}"})
|
||||||
|
|
||||||
return {k: v for k, v in attrs.items() if k not in self.readonly_fields}
|
return {k: v for k, v in attrs.items() if k not in self.readonly_fields}
|
||||||
|
|
||||||
def update(self, instance: HierarkeyProxy, validated_data):
|
def update(self, instance: HierarkeyProxy, validated_data):
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ with scopes_disabled():
|
|||||||
class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||||
serializer_class = SubEventSerializer
|
serializer_class = SubEventSerializer
|
||||||
queryset = SubEvent.objects.none()
|
queryset = SubEvent.objects.none()
|
||||||
write_permission = 'event.settings.general:write'
|
write_permission = 'event.subevents:write'
|
||||||
filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
|
filter_backends = (DjangoFilterBackend, TotalOrderingFilter)
|
||||||
ordering = ('date_from',)
|
ordering = ('date_from',)
|
||||||
ordering_fields = ('id', 'date_from', 'last_modified')
|
ordering_fields = ('id', 'date_from', 'last_modified')
|
||||||
@@ -552,7 +552,7 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet):
|
|||||||
class TaxRuleViewSet(ConditionalListView, viewsets.ModelViewSet):
|
class TaxRuleViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||||
serializer_class = TaxRuleSerializer
|
serializer_class = TaxRuleSerializer
|
||||||
queryset = TaxRule.objects.none()
|
queryset = TaxRule.objects.none()
|
||||||
write_permission = 'event.settings.general:write'
|
write_permission = 'event.settings.tax:write'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.request.event.tax_rules.all()
|
return self.request.event.tax_rules.all()
|
||||||
@@ -647,14 +647,13 @@ class EventSettingsView(views.APIView):
|
|||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
if isinstance(request.auth, Device):
|
if isinstance(request.auth, Device):
|
||||||
s = DeviceEventSettingsSerializer(instance=request.event.settings, event=request.event, context={
|
s = DeviceEventSettingsSerializer(instance=request.event.settings, event=request.event, context={
|
||||||
'request': request
|
'request': request, 'permissions': request.eventpermset
|
||||||
})
|
|
||||||
elif 'event.settings.general:write' in request.eventpermset:
|
|
||||||
s = EventSettingsSerializer(instance=request.event.settings, event=request.event, context={
|
|
||||||
'request': request
|
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
raise PermissionDenied()
|
s = EventSettingsSerializer(instance=request.event.settings, event=request.event, context={
|
||||||
|
'request': request, 'permissions': request.eventpermset,
|
||||||
|
})
|
||||||
|
|
||||||
if 'explain' in request.GET:
|
if 'explain' in request.GET:
|
||||||
return Response({
|
return Response({
|
||||||
fname: {
|
fname: {
|
||||||
@@ -668,7 +667,7 @@ class EventSettingsView(views.APIView):
|
|||||||
|
|
||||||
def patch(self, request, *wargs, **kwargs):
|
def patch(self, request, *wargs, **kwargs):
|
||||||
s = EventSettingsSerializer(instance=request.event.settings, data=request.data, partial=True,
|
s = EventSettingsSerializer(instance=request.event.settings, data=request.data, partial=True,
|
||||||
event=request.event, context={'request': request})
|
event=request.event, context={'request': request, 'permissions': request.eventpermset})
|
||||||
s.is_valid(raise_exception=True)
|
s.is_valid(raise_exception=True)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
s.save()
|
s.save()
|
||||||
@@ -680,7 +679,7 @@ class EventSettingsView(views.APIView):
|
|||||||
)
|
)
|
||||||
s = EventSettingsSerializer(
|
s = EventSettingsSerializer(
|
||||||
instance=request.event.settings, event=request.event, context={
|
instance=request.event.settings, event=request.event, context={
|
||||||
'request': request
|
'request': request, 'permissions': request.eventpermset
|
||||||
})
|
})
|
||||||
return Response(s.data)
|
return Response(s.data)
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ class ReusableMediaViewSet(viewsets.ModelViewSet):
|
|||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
ctx = super().get_serializer_context()
|
ctx = super().get_serializer_context()
|
||||||
ctx['organizer'] = self.request.organizer
|
ctx['organizer'] = self.request.organizer
|
||||||
|
ctx['can_read_giftcards'] = 'organizer.giftcards:read' in self.request.orgapermset
|
||||||
|
ctx['can_read_customers'] = 'organizer.customers:read' in self.request.orgapermset
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
@transaction.atomic()
|
@transaction.atomic()
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ with scopes_disabled():
|
|||||||
class GiftCardViewSet(viewsets.ModelViewSet):
|
class GiftCardViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = GiftCardSerializer
|
serializer_class = GiftCardSerializer
|
||||||
queryset = GiftCard.objects.none()
|
queryset = GiftCard.objects.none()
|
||||||
permission = 'organizer.giftcards:write'
|
permission = 'organizer.giftcards:read'
|
||||||
write_permission = 'organizer.giftcards:write'
|
write_permission = 'organizer.giftcards:write'
|
||||||
filter_backends = (DjangoFilterBackend,)
|
filter_backends = (DjangoFilterBackend,)
|
||||||
filterset_class = GiftCardFilter
|
filterset_class = GiftCardFilter
|
||||||
@@ -344,7 +344,7 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
|||||||
class GiftCardTransactionViewSet(viewsets.ReadOnlyModelViewSet):
|
class GiftCardTransactionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
serializer_class = GiftCardTransactionSerializer
|
serializer_class = GiftCardTransactionSerializer
|
||||||
queryset = GiftCardTransaction.objects.none()
|
queryset = GiftCardTransaction.objects.none()
|
||||||
permission = 'organizer.giftcards:write'
|
permission = 'organizer.giftcards:read'
|
||||||
write_permission = 'organizer.giftcards:write'
|
write_permission = 'organizer.giftcards:write'
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@@ -532,8 +532,8 @@ class DeviceViewSet(mixins.CreateModelMixin,
|
|||||||
GenericViewSet):
|
GenericViewSet):
|
||||||
serializer_class = DeviceSerializer
|
serializer_class = DeviceSerializer
|
||||||
queryset = Device.objects.none()
|
queryset = Device.objects.none()
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:read'
|
||||||
write_permission = 'organizer.settings.general:write'
|
write_permission = 'organizer.devices:write'
|
||||||
lookup_field = 'device_id'
|
lookup_field = 'device_id'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
@@ -542,6 +542,9 @@ class DeviceViewSet(mixins.CreateModelMixin,
|
|||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
ctx = super().get_serializer_context()
|
ctx = super().get_serializer_context()
|
||||||
ctx['organizer'] = self.request.organizer
|
ctx['organizer'] = self.request.organizer
|
||||||
|
ctx['can_see_tokens'] = (
|
||||||
|
self.request.user if self.request.user and self.request.user.is_authenticated else self.request.auth
|
||||||
|
).has_organizer_permission(self.request.organizer, 'organizer.devices:write', request=self.request)
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
@transaction.atomic()
|
@transaction.atomic()
|
||||||
@@ -572,7 +575,7 @@ class OrganizerSettingsView(views.APIView):
|
|||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
||||||
'request': request
|
'request': request, 'permissions': request.orgapermset
|
||||||
})
|
})
|
||||||
if 'explain' in request.GET:
|
if 'explain' in request.GET:
|
||||||
return Response({
|
return Response({
|
||||||
@@ -589,7 +592,7 @@ class OrganizerSettingsView(views.APIView):
|
|||||||
s = OrganizerSettingsSerializer(
|
s = OrganizerSettingsSerializer(
|
||||||
instance=request.organizer.settings, data=request.data, partial=True,
|
instance=request.organizer.settings, data=request.data, partial=True,
|
||||||
organizer=request.organizer, context={
|
organizer=request.organizer, context={
|
||||||
'request': request
|
'request': request, 'permissions': request.orgapermset
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
s.is_valid(raise_exception=True)
|
s.is_valid(raise_exception=True)
|
||||||
@@ -601,7 +604,7 @@ class OrganizerSettingsView(views.APIView):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={
|
||||||
'request': request
|
'request': request, 'permissions': request.orgapermset
|
||||||
})
|
})
|
||||||
return Response(s.data)
|
return Response(s.data)
|
||||||
|
|
||||||
@@ -618,7 +621,8 @@ with scopes_disabled():
|
|||||||
class CustomerViewSet(viewsets.ModelViewSet):
|
class CustomerViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = CustomerSerializer
|
serializer_class = CustomerSerializer
|
||||||
queryset = Customer.objects.none()
|
queryset = Customer.objects.none()
|
||||||
permission = 'organizer.customers:write'
|
permission = 'organizer.customers:read'
|
||||||
|
write_permission = 'organizer.customers:write'
|
||||||
lookup_field = 'identifier'
|
lookup_field = 'identifier'
|
||||||
filter_backends = (DjangoFilterBackend,)
|
filter_backends = (DjangoFilterBackend,)
|
||||||
filterset_class = CustomerFilter
|
filterset_class = CustomerFilter
|
||||||
@@ -735,7 +739,8 @@ with scopes_disabled():
|
|||||||
class MembershipViewSet(viewsets.ModelViewSet):
|
class MembershipViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = MembershipSerializer
|
serializer_class = MembershipSerializer
|
||||||
queryset = Membership.objects.none()
|
queryset = Membership.objects.none()
|
||||||
permission = 'organizer.customers:write'
|
permission = 'organizer.customers:read'
|
||||||
|
write_permission = 'organizer.customers:write'
|
||||||
filter_backends = (DjangoFilterBackend,)
|
filter_backends = (DjangoFilterBackend,)
|
||||||
filterset_class = MembershipFilter
|
filterset_class = MembershipFilter
|
||||||
|
|
||||||
|
|||||||
@@ -78,18 +78,18 @@ def register_default_event_permissions(sender, **kwargs):
|
|||||||
Permission("event.settings.general:write", _("Change general settings"), None,
|
Permission("event.settings.general:write", _("Change general settings"), None,
|
||||||
_("This includes access to all settings not listed explicitly below, including plugin settings.")),
|
_("This includes access to all settings not listed explicitly below, including plugin settings.")),
|
||||||
Permission("event.settings.payment:write", _("Change payment settings"), None, None),
|
Permission("event.settings.payment:write", _("Change payment settings"), None, None),
|
||||||
Permission("event.settings.plugins:write", _("Change plugin settings"), None, None),
|
|
||||||
Permission("event.settings.email.sender:write", _("Change email sending settings"), None, None),
|
|
||||||
Permission("event.settings.tax:write", _("Change tax rules"), None, None),
|
Permission("event.settings.tax:write", _("Change tax rules"), None, None),
|
||||||
Permission("event.settings.invoicing:write", _("Change invoicing settings"), None, None),
|
Permission("event.settings.invoicing:write", _("Change invoicing settings"), None, None),
|
||||||
Permission("event.subevents:write", pgettext_lazy("subevent", "Change event series dates"), None, None),
|
Permission("event.subevents:write", pgettext_lazy("subevent", "Change event series dates"), None,
|
||||||
Permission("event.items:write", _("Change products and quotas"), None, None), # and questions but that might change?
|
_("Read access is granted to all teams with access to the event.")),
|
||||||
|
Permission("event.items:write", _("Change products, quotas, and questions"), None,
|
||||||
|
_("Also includes related objects like categories or discounts. Read access is granted to all teams with access to the event.")),
|
||||||
Permission("event.orders:read", _("View orders"), None, None),
|
Permission("event.orders:read", _("View orders"), None, None),
|
||||||
Permission("event.orders:write", _("Change orders"), None, _("This includes the ability to cancel and refund individual orders.")),
|
Permission("event.orders:write", _("Change orders"), None, _("This includes the ability to cancel and refund individual orders.")),
|
||||||
Permission("event.orders:checkin", _("Check-in orders"), None, None),
|
Permission("event.orders:checkin", _("Check-in orders"), None, None),
|
||||||
Permission("event.vouchers:read", _("View vouchers"), None, None),
|
Permission("event.vouchers:read", _("View vouchers"), None, None),
|
||||||
Permission("event.vouchers:write", _("Change vouchers"), None, None),
|
Permission("event.vouchers:write", _("Change vouchers"), None, None),
|
||||||
Permission("event:cancel", pgettext_lazy("subevent", " entire event or date"), None, None),
|
Permission("event:cancel", pgettext_lazy("subevent", "Cancel entire event or date"), None, None),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -100,14 +100,16 @@ def register_default_organizer_permissions(sender, **kwargs):
|
|||||||
Permission("organizer.settings.general:write", _("Change settings"), None,
|
Permission("organizer.settings.general:write", _("Change settings"), None,
|
||||||
_("This includes access to all organizer-level functionality not listed explicitly below, including plugin settings.")),
|
_("This includes access to all organizer-level functionality not listed explicitly below, including plugin settings.")),
|
||||||
Permission("organizer.teams:write", _("Change teams"), None,
|
Permission("organizer.teams:write", _("Change teams"), None,
|
||||||
_("This includes the ability to give someone (including oneself) additional permissions.")),
|
_("This includes the ability to give someone (including oneself) additional permissions. Read access "
|
||||||
|
"is implicitly granted to the same team.")),
|
||||||
Permission("organizer.giftcards:read", _("View gift cards"), None, None),
|
Permission("organizer.giftcards:read", _("View gift cards"), None, None),
|
||||||
Permission("organizer.giftcards:write", _("Change gift cards"), None, None),
|
Permission("organizer.giftcards:write", _("Change gift cards"), None, None),
|
||||||
Permission("organizer.customers:read", _("View customer accounts"), None, None),
|
Permission("organizer.customers:read", _("View customer accounts"), None, None),
|
||||||
Permission("organizer.customers:write", _("Change customer accounts"), None, None),
|
Permission("organizer.customers:write", _("Change customer accounts"), None, None),
|
||||||
Permission("organizer.reusablemedia:read", _("View reusable media"), None, None),
|
Permission("organizer.reusablemedia:read", _("View reusable media"), None,
|
||||||
|
_("This includes access to data of tickets connected to reusable media.")),
|
||||||
Permission("organizer.reusablemedia:write", _("Change reusable media"), None, None),
|
Permission("organizer.reusablemedia:write", _("Change reusable media"), None, None),
|
||||||
Permission("organizer.devices:read", _("View devices"), None, None),
|
Permission("organizer.devices:read", _("View devices and gates"), None, None),
|
||||||
Permission("organizer.devices:write", _("Change devices"), None,
|
Permission("organizer.devices:write", _("Change devices and gates"), None,
|
||||||
_("This includes the ability to give access to events and data oneself does not have access to.")),
|
_("This includes the ability to give access to events and data oneself does not have access to.")),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -345,6 +345,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.tax:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show net prices instead of gross prices in the product list"),
|
label=_("Show net prices instead of gross prices in the product list"),
|
||||||
help_text=_("Independent of your choice, the cart will show gross prices as this is the price that needs to be "
|
help_text=_("Independent of your choice, the cart will show gross prices as this is the price that needs to be "
|
||||||
@@ -492,6 +493,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.ChoiceField,
|
'form_class': forms.ChoiceField,
|
||||||
'serializer_class': serializers.ChoiceField,
|
'serializer_class': serializers.ChoiceField,
|
||||||
|
'write_permission': 'event.settings.tax:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Rounding of taxes"),
|
label=_("Rounding of taxes"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -511,15 +513,17 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Ask for invoice address"),
|
label=_("Ask for invoice address"),
|
||||||
)
|
),
|
||||||
},
|
},
|
||||||
'invoice_address_not_asked_free': {
|
'invoice_address_not_asked_free': {
|
||||||
'default': 'False',
|
'default': 'False',
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Do not ask for invoice address if an order is free'),
|
label=_('Do not ask for invoice address if an order is free'),
|
||||||
)
|
)
|
||||||
@@ -529,6 +533,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Require customer name"),
|
label=_("Require customer name"),
|
||||||
)
|
)
|
||||||
@@ -538,6 +543,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show attendee names on invoices"),
|
label=_("Show attendee names on invoices"),
|
||||||
)
|
)
|
||||||
@@ -547,6 +553,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show event location on invoices"),
|
label=_("Show event location on invoices"),
|
||||||
help_text=_("The event location will be shown below the list of products if it is the same for all "
|
help_text=_("The event location will be shown below the list of products if it is the same for all "
|
||||||
@@ -558,6 +565,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.ChoiceField,
|
'form_class': forms.ChoiceField,
|
||||||
'serializer_class': serializers.ChoiceField,
|
'serializer_class': serializers.ChoiceField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show exchange rates"),
|
label=_("Show exchange rates"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -581,6 +589,7 @@ DEFAULTS = {
|
|||||||
'default': 'False',
|
'default': 'False',
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Require invoice address"),
|
label=_("Require invoice address"),
|
||||||
@@ -591,6 +600,7 @@ DEFAULTS = {
|
|||||||
'default': 'False',
|
'default': 'False',
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Require a business address"),
|
label=_("Require a business address"),
|
||||||
@@ -603,6 +613,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Ask for beneficiary"),
|
label=_("Ask for beneficiary"),
|
||||||
widget=forms.CheckboxInput(attrs={'data-checkbox-dependency': '#id_invoice_address_asked'}),
|
widget=forms.CheckboxInput(attrs={'data-checkbox-dependency': '#id_invoice_address_asked'}),
|
||||||
@@ -613,6 +624,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Custom recipient field label"),
|
label=_("Custom recipient field label"),
|
||||||
widget=I18nTextInput,
|
widget=I18nTextInput,
|
||||||
@@ -628,6 +640,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Custom recipient field help text"),
|
label=_("Custom recipient field help text"),
|
||||||
widget=I18nTextInput,
|
widget=I18nTextInput,
|
||||||
@@ -640,6 +653,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Ask for VAT ID"),
|
label=_("Ask for VAT ID"),
|
||||||
help_text=format_lazy(
|
help_text=format_lazy(
|
||||||
@@ -655,6 +669,7 @@ DEFAULTS = {
|
|||||||
'type': list,
|
'type': list,
|
||||||
'form_class': forms.MultipleChoiceField,
|
'form_class': forms.MultipleChoiceField,
|
||||||
'serializer_class': serializers.MultipleChoiceField,
|
'serializer_class': serializers.MultipleChoiceField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'serializer_kwargs': dict(
|
'serializer_kwargs': dict(
|
||||||
choices=lazy(
|
choices=lazy(
|
||||||
lambda *args: sorted([(cc, gettext(Country(cc).name)) for cc in VAT_ID_COUNTRIES], key=lambda c: c[1]),
|
lambda *args: sorted([(cc, gettext(Country(cc).name)) for cc in VAT_ID_COUNTRIES], key=lambda c: c[1]),
|
||||||
@@ -682,6 +697,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Invoice address explanation"),
|
label=_("Invoice address explanation"),
|
||||||
widget=I18nMarkdownTextarea,
|
widget=I18nMarkdownTextarea,
|
||||||
@@ -694,6 +710,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show paid amount on partially paid invoices"),
|
label=_("Show paid amount on partially paid invoices"),
|
||||||
help_text=_("If an invoice has already been paid partially, this option will add the paid and pending "
|
help_text=_("If an invoice has already been paid partially, this option will add the paid and pending "
|
||||||
@@ -705,6 +722,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show free products on invoices"),
|
label=_("Show free products on invoices"),
|
||||||
help_text=_("Note that invoices will never be generated for orders that contain only free "
|
help_text=_("Note that invoices will never be generated for orders that contain only free "
|
||||||
@@ -716,6 +734,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show expiration date of order"),
|
label=_("Show expiration date of order"),
|
||||||
help_text=_("The expiration date will not be shown if the invoice is generated after the order is paid."),
|
help_text=_("The expiration date will not be shown if the invoice is generated after the order is paid."),
|
||||||
@@ -727,6 +746,7 @@ DEFAULTS = {
|
|||||||
'form_class': forms.IntegerField,
|
'form_class': forms.IntegerField,
|
||||||
'serializer_class': serializers.IntegerField,
|
'serializer_class': serializers.IntegerField,
|
||||||
'serializer_kwargs': dict(),
|
'serializer_kwargs': dict(),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Minimum length of invoice number after prefix"),
|
label=_("Minimum length of invoice number after prefix"),
|
||||||
help_text=_("The part of your invoice number after your prefix will be filled up with leading zeros up to this length, e.g. INV-001 or INV-00001."),
|
help_text=_("The part of your invoice number after your prefix will be filled up with leading zeros up to this length, e.g. INV-001 or INV-00001."),
|
||||||
@@ -740,6 +760,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Generate invoices with consecutive numbers"),
|
label=_("Generate invoices with consecutive numbers"),
|
||||||
help_text=_("If deactivated, the order code will be used in the invoice number."),
|
help_text=_("If deactivated, the order code will be used in the invoice number."),
|
||||||
@@ -750,6 +771,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Invoice number prefix"),
|
label=_("Invoice number prefix"),
|
||||||
help_text=_("This will be prepended to invoice numbers. If you leave this field empty, your event slug will "
|
help_text=_("This will be prepended to invoice numbers. If you leave this field empty, your event slug will "
|
||||||
@@ -777,6 +799,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Invoice number prefix for cancellations"),
|
label=_("Invoice number prefix for cancellations"),
|
||||||
help_text=_("This will be prepended to invoice numbers of cancellations. If you leave this field empty, "
|
help_text=_("This will be prepended to invoice numbers of cancellations. If you leave this field empty, "
|
||||||
@@ -800,6 +823,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Highlight order code to make it stand out visibly"),
|
label=_("Highlight order code to make it stand out visibly"),
|
||||||
help_text=_("Only respected by some invoice renderers."),
|
help_text=_("Only respected by some invoice renderers."),
|
||||||
@@ -811,6 +835,7 @@ DEFAULTS = {
|
|||||||
'form_class': forms.ChoiceField,
|
'form_class': forms.ChoiceField,
|
||||||
'serializer_class': serializers.ChoiceField,
|
'serializer_class': serializers.ChoiceField,
|
||||||
'serializer_kwargs': lambda: dict(**invoice_font_kwargs()),
|
'serializer_kwargs': lambda: dict(**invoice_font_kwargs()),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': lambda: dict(
|
'form_kwargs': lambda: dict(
|
||||||
label=_('Font'),
|
label=_('Font'),
|
||||||
help_text=_("Only respected by some invoice renderers."),
|
help_text=_("Only respected by some invoice renderers."),
|
||||||
@@ -821,6 +846,7 @@ DEFAULTS = {
|
|||||||
'invoice_renderer': {
|
'invoice_renderer': {
|
||||||
'default': 'classic', # default for new events is 'modern1'
|
'default': 'classic', # default for new events is 'modern1'
|
||||||
'type': str,
|
'type': str,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
},
|
},
|
||||||
'ticket_secret_generator': {
|
'ticket_secret_generator': {
|
||||||
'default': 'random',
|
'default': 'random',
|
||||||
@@ -897,6 +923,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=I18nMarkdownTextarea,
|
widget=I18nMarkdownTextarea,
|
||||||
widget_kwargs={'attrs': {
|
widget_kwargs={'attrs': {
|
||||||
@@ -918,6 +945,7 @@ DEFAULTS = {
|
|||||||
('minutes', _("in minutes"))
|
('minutes', _("in minutes"))
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Set payment term"),
|
label=_("Set payment term"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -935,6 +963,7 @@ DEFAULTS = {
|
|||||||
'type': int,
|
'type': int,
|
||||||
'form_class': forms.IntegerField,
|
'form_class': forms.IntegerField,
|
||||||
'serializer_class': serializers.IntegerField,
|
'serializer_class': serializers.IntegerField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Payment term in days'),
|
label=_('Payment term in days'),
|
||||||
widget=forms.NumberInput(
|
widget=forms.NumberInput(
|
||||||
@@ -960,6 +989,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Only end payment terms on weekdays'),
|
label=_('Only end payment terms on weekdays'),
|
||||||
help_text=_("If this is activated and the payment term of any order ends on a Saturday or Sunday, it will be "
|
help_text=_("If this is activated and the payment term of any order ends on a Saturday or Sunday, it will be "
|
||||||
@@ -977,6 +1007,7 @@ DEFAULTS = {
|
|||||||
'type': int,
|
'type': int,
|
||||||
'form_class': forms.IntegerField,
|
'form_class': forms.IntegerField,
|
||||||
'serializer_class': serializers.IntegerField,
|
'serializer_class': serializers.IntegerField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Payment term in minutes'),
|
label=_('Payment term in minutes'),
|
||||||
help_text=_("The number of minutes after placing an order the user has to pay to preserve their reservation. "
|
help_text=_("The number of minutes after placing an order the user has to pay to preserve their reservation. "
|
||||||
@@ -1001,6 +1032,7 @@ DEFAULTS = {
|
|||||||
'type': RelativeDateWrapper,
|
'type': RelativeDateWrapper,
|
||||||
'form_class': RelativeDateField,
|
'form_class': RelativeDateField,
|
||||||
'serializer_class': SerializerRelativeDateField,
|
'serializer_class': SerializerRelativeDateField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Last date of payments'),
|
label=_('Last date of payments'),
|
||||||
help_text=_("The last date any payments are accepted. This has precedence over the terms "
|
help_text=_("The last date any payments are accepted. This has precedence over the terms "
|
||||||
@@ -1013,6 +1045,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Automatically expire unpaid orders'),
|
label=_('Automatically expire unpaid orders'),
|
||||||
help_text=_("If checked, all unpaid orders will automatically go from 'pending' to 'expired' "
|
help_text=_("If checked, all unpaid orders will automatically go from 'pending' to 'expired' "
|
||||||
@@ -1025,6 +1058,7 @@ DEFAULTS = {
|
|||||||
'type': int,
|
'type': int,
|
||||||
'form_class': forms.IntegerField,
|
'form_class': forms.IntegerField,
|
||||||
'serializer_class': serializers.IntegerField,
|
'serializer_class': serializers.IntegerField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Expiration delay'),
|
label=_('Expiration delay'),
|
||||||
help_text=_("The order will only actually expire this many days after the expiration date communicated "
|
help_text=_("The order will only actually expire this many days after the expiration date communicated "
|
||||||
@@ -1047,6 +1081,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Hide "payment pending" state on customer-facing pages'),
|
label=_('Hide "payment pending" state on customer-facing pages'),
|
||||||
help_text=_("The payment instructions panel will still be shown to the primary customer, but no indication "
|
help_text=_("The payment instructions panel will still be shown to the primary customer, but no indication "
|
||||||
@@ -1058,9 +1093,11 @@ DEFAULTS = {
|
|||||||
'default': 'True',
|
'default': 'True',
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
},
|
},
|
||||||
'payment_giftcard_public_name': {
|
'payment_giftcard_public_name': {
|
||||||
'default': LazyI18nString.from_gettext(gettext_noop('Gift card')),
|
'default': LazyI18nString.from_gettext(gettext_noop('Gift card')),
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'type': LazyI18nString
|
'type': LazyI18nString
|
||||||
},
|
},
|
||||||
'payment_giftcard_public_description': {
|
'payment_giftcard_public_description': {
|
||||||
@@ -1069,10 +1106,12 @@ DEFAULTS = {
|
|||||||
'enough credit to pay for the full order, you will be shown this page again and you can either '
|
'enough credit to pay for the full order, you will be shown this page again and you can either '
|
||||||
'redeem another gift card or select a different payment method for the difference.'
|
'redeem another gift card or select a different payment method for the difference.'
|
||||||
)),
|
)),
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'type': LazyI18nString
|
'type': LazyI18nString
|
||||||
},
|
},
|
||||||
'payment_resellers__restrict_to_sales_channels': {
|
'payment_resellers__restrict_to_sales_channels': {
|
||||||
'default': ['resellers'],
|
'default': ['resellers'],
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'type': list
|
'type': list
|
||||||
},
|
},
|
||||||
'payment_term_accept_late': {
|
'payment_term_accept_late': {
|
||||||
@@ -1080,6 +1119,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_('Accept late payments'),
|
label=_('Accept late payments'),
|
||||||
help_text=_("Accept payments for orders even when they are in 'expired' state as long as enough "
|
help_text=_("Accept payments for orders even when they are in 'expired' state as long as enough "
|
||||||
@@ -1109,6 +1149,7 @@ DEFAULTS = {
|
|||||||
('none', _('Charge no taxes')),
|
('none', _('Charge no taxes')),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'write_permission': 'event.settings.payment:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Tax handling on payment fees"),
|
label=_("Tax handling on payment fees"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -1155,6 +1196,7 @@ DEFAULTS = {
|
|||||||
('paid', _('Automatically on payment or when required by payment method')),
|
('paid', _('Automatically on payment or when required by payment method')),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Generate invoices"),
|
label=_("Generate invoices"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -1183,6 +1225,7 @@ DEFAULTS = {
|
|||||||
('invoice_date', _('Invoice date')),
|
('invoice_date', _('Invoice date')),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Date of service"),
|
label=_("Date of service"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
@@ -1203,6 +1246,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Automatically cancel and reissue invoice on address changes"),
|
label=_("Automatically cancel and reissue invoice on address changes"),
|
||||||
help_text=_("If customers change their invoice address on an existing order, the invoice will "
|
help_text=_("If customers change their invoice address on an existing order, the invoice will "
|
||||||
@@ -1215,6 +1259,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Allow to update existing invoices"),
|
label=_("Allow to update existing invoices"),
|
||||||
help_text=_("By default, invoices can never again be changed once they are issued. In most countries, we "
|
help_text=_("By default, invoices can never again be changed once they are issued. In most countries, we "
|
||||||
@@ -1224,6 +1269,7 @@ DEFAULTS = {
|
|||||||
},
|
},
|
||||||
'invoice_generate_sales_channels': {
|
'invoice_generate_sales_channels': {
|
||||||
'default': json.dumps(['web']),
|
'default': json.dumps(['web']),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'type': list
|
'type': list
|
||||||
},
|
},
|
||||||
'invoice_generate_only_business': {
|
'invoice_generate_only_business': {
|
||||||
@@ -1240,6 +1286,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Address line"),
|
label=_("Address line"),
|
||||||
widget=forms.Textarea(attrs={
|
widget=forms.Textarea(attrs={
|
||||||
@@ -1255,6 +1302,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
max_length=190,
|
max_length=190,
|
||||||
label=_("Company name"),
|
label=_("Company name"),
|
||||||
@@ -1265,6 +1313,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=forms.TextInput(attrs={
|
widget=forms.TextInput(attrs={
|
||||||
'placeholder': '12345'
|
'placeholder': '12345'
|
||||||
@@ -1278,6 +1327,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=forms.TextInput(attrs={
|
widget=forms.TextInput(attrs={
|
||||||
'placeholder': _('Random City')
|
'placeholder': _('Random City')
|
||||||
@@ -1294,6 +1344,7 @@ DEFAULTS = {
|
|||||||
'serializer_kwargs': {
|
'serializer_kwargs': {
|
||||||
'choices': [('', '')],
|
'choices': [('', '')],
|
||||||
},
|
},
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': {
|
'form_kwargs': {
|
||||||
"label": pgettext_lazy('address', 'State'),
|
"label": pgettext_lazy('address', 'State'),
|
||||||
'choices': [('', '')],
|
'choices': [('', '')],
|
||||||
@@ -1305,6 +1356,7 @@ DEFAULTS = {
|
|||||||
'form_class': forms.ChoiceField,
|
'form_class': forms.ChoiceField,
|
||||||
'serializer_class': serializers.ChoiceField,
|
'serializer_class': serializers.ChoiceField,
|
||||||
'serializer_kwargs': lambda: dict(**country_choice_kwargs()),
|
'serializer_kwargs': lambda: dict(**country_choice_kwargs()),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': lambda: dict(
|
'form_kwargs': lambda: dict(
|
||||||
label=_('Country'),
|
label=_('Country'),
|
||||||
widget=forms.Select(attrs={
|
widget=forms.Select(attrs={
|
||||||
@@ -1318,6 +1370,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Domestic tax ID"),
|
label=_("Domestic tax ID"),
|
||||||
help_text=_("e.g. tax number in Germany, ABN in Australia, …"),
|
help_text=_("e.g. tax number in Germany, ABN in Australia, …"),
|
||||||
@@ -1329,6 +1382,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("EU VAT ID"),
|
label=_("EU VAT ID"),
|
||||||
max_length=190,
|
max_length=190,
|
||||||
@@ -1339,6 +1393,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=I18nTextarea,
|
widget=I18nTextarea,
|
||||||
widget_kwargs={'attrs': {
|
widget_kwargs={'attrs': {
|
||||||
@@ -1356,6 +1411,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=I18nTextarea,
|
widget=I18nTextarea,
|
||||||
widget_kwargs={'attrs': {
|
widget_kwargs={'attrs': {
|
||||||
@@ -1373,6 +1429,7 @@ DEFAULTS = {
|
|||||||
'type': LazyI18nString,
|
'type': LazyI18nString,
|
||||||
'form_class': I18nFormField,
|
'form_class': I18nFormField,
|
||||||
'serializer_class': I18nField,
|
'serializer_class': I18nField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
widget=I18nTextarea,
|
widget=I18nTextarea,
|
||||||
widget_kwargs={'attrs': {
|
widget_kwargs={'attrs': {
|
||||||
@@ -1387,6 +1444,7 @@ DEFAULTS = {
|
|||||||
},
|
},
|
||||||
'invoice_language': {
|
'invoice_language': {
|
||||||
'default': '__user__',
|
'default': '__user__',
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'type': str
|
'type': str
|
||||||
},
|
},
|
||||||
'invoice_email_attachment': {
|
'invoice_email_attachment': {
|
||||||
@@ -1394,6 +1452,7 @@ DEFAULTS = {
|
|||||||
'type': bool,
|
'type': bool,
|
||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Attach invoices to emails"),
|
label=_("Attach invoices to emails"),
|
||||||
help_text=_("If invoices are automatically generated for all orders, they will be attached to the order "
|
help_text=_("If invoices are automatically generated for all orders, they will be attached to the order "
|
||||||
@@ -1407,6 +1466,7 @@ DEFAULTS = {
|
|||||||
'type': str,
|
'type': str,
|
||||||
'form_class': forms.CharField,
|
'form_class': forms.CharField,
|
||||||
'serializer_class': serializers.CharField,
|
'serializer_class': serializers.CharField,
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Email address to receive a copy of each invoice"),
|
label=_("Email address to receive a copy of each invoice"),
|
||||||
help_text=_("Each newly created invoice will be sent to this email address shortly after creation. You can "
|
help_text=_("Each newly created invoice will be sent to this email address shortly after creation. You can "
|
||||||
@@ -3260,7 +3320,8 @@ Your {organizer} team""")) # noqa: W291
|
|||||||
'image/png', 'image/jpeg', 'image/gif'
|
'image/png', 'image/jpeg', 'image/gif'
|
||||||
],
|
],
|
||||||
max_size=settings.FILE_UPLOAD_MAX_SIZE_IMAGE,
|
max_size=settings.FILE_UPLOAD_MAX_SIZE_IMAGE,
|
||||||
)
|
),
|
||||||
|
'write_permission': 'event.settings.invoicing:write',
|
||||||
},
|
},
|
||||||
'frontpage_text': {
|
'frontpage_text': {
|
||||||
'default': '',
|
'default': '',
|
||||||
|
|||||||
@@ -1118,6 +1118,9 @@ api_event_settings_fields = EventPluginSignal()
|
|||||||
This signal is sent out to collect serializable settings fields for the API. You are expected to
|
This signal is sent out to collect serializable settings fields for the API. You are expected to
|
||||||
return a dictionary mapping names of attributes in the settings store to DRF serializer field instances.
|
return a dictionary mapping names of attributes in the settings store to DRF serializer field instances.
|
||||||
|
|
||||||
|
These are readable for all users with access to the events, therefore secrets made in the settings store
|
||||||
|
should not be included!
|
||||||
|
|
||||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ from pretix.base.models import ItemVariation
|
|||||||
from pretix.base.reldate import RelativeDateWrapper
|
from pretix.base.reldate import RelativeDateWrapper
|
||||||
from pretix.base.signals import timeline_events
|
from pretix.base.signals import timeline_events
|
||||||
|
|
||||||
TimelineEvent = namedtuple('TimelineEvent', ('event', 'subevent', 'datetime', 'description', 'edit_url'))
|
TimelineEvent = namedtuple(
|
||||||
|
'TimelineEvent',
|
||||||
|
('event', 'subevent', 'datetime', 'description', 'edit_url', 'edit_permission'),
|
||||||
|
defaults=(None, None, None, None, None, 'event.settings.general:write')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def timeline_for_event(event, subevent=None):
|
def timeline_for_event(event, subevent=None):
|
||||||
@@ -46,6 +50,7 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'subevent': subevent.pk
|
'subevent': subevent.pk
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ev_edit_permission = 'event.subevents:write'
|
||||||
else:
|
else:
|
||||||
ev_edit_url = reverse(
|
ev_edit_url = reverse(
|
||||||
'control:event.settings', kwargs={
|
'control:event.settings', kwargs={
|
||||||
@@ -53,12 +58,14 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ev_edit_permission = 'event.settings.general:write'
|
||||||
|
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
event=event, subevent=subevent,
|
event=event, subevent=subevent,
|
||||||
datetime=ev.date_from,
|
datetime=ev.date_from,
|
||||||
description=pgettext_lazy('timeline', 'Your event starts'),
|
description=pgettext_lazy('timeline', 'Your event starts'),
|
||||||
edit_url=ev_edit_url + '#id_date_from_0'
|
edit_url=ev_edit_url + '#id_date_from_0',
|
||||||
|
edit_permission=ev_edit_permission,
|
||||||
))
|
))
|
||||||
|
|
||||||
if ev.date_to:
|
if ev.date_to:
|
||||||
@@ -66,7 +73,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
event=event, subevent=subevent,
|
event=event, subevent=subevent,
|
||||||
datetime=ev.date_to,
|
datetime=ev.date_to,
|
||||||
description=pgettext_lazy('timeline', 'Your event ends'),
|
description=pgettext_lazy('timeline', 'Your event ends'),
|
||||||
edit_url=ev_edit_url + '#id_date_to_0'
|
edit_url=ev_edit_url + '#id_date_to_0',
|
||||||
|
edit_permission=ev_edit_permission,
|
||||||
))
|
))
|
||||||
|
|
||||||
if ev.date_admission:
|
if ev.date_admission:
|
||||||
@@ -74,7 +82,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
event=event, subevent=subevent,
|
event=event, subevent=subevent,
|
||||||
datetime=ev.date_admission,
|
datetime=ev.date_admission,
|
||||||
description=pgettext_lazy('timeline', 'Admissions for your event start'),
|
description=pgettext_lazy('timeline', 'Admissions for your event start'),
|
||||||
edit_url=ev_edit_url + '#id_date_admission_0'
|
edit_url=ev_edit_url + '#id_date_admission_0',
|
||||||
|
edit_permission=ev_edit_permission,
|
||||||
))
|
))
|
||||||
|
|
||||||
if ev.presale_start:
|
if ev.presale_start:
|
||||||
@@ -82,7 +91,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
event=event, subevent=subevent,
|
event=event, subevent=subevent,
|
||||||
datetime=ev.presale_start,
|
datetime=ev.presale_start,
|
||||||
description=pgettext_lazy('timeline', 'Start of ticket sales'),
|
description=pgettext_lazy('timeline', 'Start of ticket sales'),
|
||||||
edit_url=ev_edit_url + '#id_presale_start_0'
|
edit_url=ev_edit_url + '#id_presale_start_0',
|
||||||
|
edit_permission=ev_edit_permission,
|
||||||
))
|
))
|
||||||
|
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -97,7 +107,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
) if not ev.presale_end else (
|
) if not ev.presale_end else (
|
||||||
pgettext_lazy('timeline', 'End of ticket sales')
|
pgettext_lazy('timeline', 'End of ticket sales')
|
||||||
),
|
),
|
||||||
edit_url=ev_edit_url + '#id_presale_end_0'
|
edit_url=ev_edit_url + '#id_presale_end_0',
|
||||||
|
edit_permission=ev_edit_permission,
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('last_order_modification_date', as_type=RelativeDateWrapper)
|
rd = event.settings.get('last_order_modification_date', as_type=RelativeDateWrapper)
|
||||||
@@ -106,7 +117,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
event=event, subevent=subevent,
|
event=event, subevent=subevent,
|
||||||
datetime=rd.datetime(ev),
|
datetime=rd.datetime(ev),
|
||||||
description=pgettext_lazy('timeline', 'Customers can no longer modify their order information'),
|
description=pgettext_lazy('timeline', 'Customers can no longer modify their order information'),
|
||||||
edit_url=ev_edit_url + '#id_settings-last_order_modification_date_0_0'
|
edit_url=ev_edit_url + '#id_settings-last_order_modification_date_0_0',
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
|
rd = event.settings.get('payment_term_last', as_type=RelativeDateWrapper)
|
||||||
@@ -122,7 +134,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.payment', kwargs={
|
edit_url=reverse('control:event.settings.payment', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.payment:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('ticket_download_date', as_type=RelativeDateWrapper)
|
rd = event.settings.get('ticket_download_date', as_type=RelativeDateWrapper)
|
||||||
@@ -134,7 +147,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.tickets', kwargs={
|
edit_url=reverse('control:event.settings.tickets', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('cancel_allow_user_until', as_type=RelativeDateWrapper)
|
rd = event.settings.get('cancel_allow_user_until', as_type=RelativeDateWrapper)
|
||||||
@@ -146,7 +160,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.cancel', kwargs={
|
edit_url=reverse('control:event.settings.cancel', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('cancel_allow_user_paid_until', as_type=RelativeDateWrapper)
|
rd = event.settings.get('cancel_allow_user_paid_until', as_type=RelativeDateWrapper)
|
||||||
@@ -158,7 +173,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.cancel', kwargs={
|
edit_url=reverse('control:event.settings.cancel', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('change_allow_user_until', as_type=RelativeDateWrapper)
|
rd = event.settings.get('change_allow_user_until', as_type=RelativeDateWrapper)
|
||||||
@@ -170,7 +186,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.cancel', kwargs={
|
edit_url=reverse('control:event.settings.cancel', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
rd = event.settings.get('waiting_list_auto_disable', as_type=RelativeDateWrapper)
|
rd = event.settings.get('waiting_list_auto_disable', as_type=RelativeDateWrapper)
|
||||||
@@ -182,7 +199,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings', kwargs={
|
edit_url=reverse('control:event.settings', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
}) + '#waiting-list-open'
|
}) + '#waiting-list-open',
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
if not event.has_subevents:
|
if not event.has_subevents:
|
||||||
@@ -196,7 +214,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
edit_url=reverse('control:event.settings.mail', kwargs={
|
edit_url=reverse('control:event.settings.mail', kwargs={
|
||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug
|
'organizer': event.organizer.slug
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.general:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
if subevent:
|
if subevent:
|
||||||
@@ -210,7 +229,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'subevent': subevent.pk,
|
'subevent': subevent.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.subevents:write',
|
||||||
))
|
))
|
||||||
if sei.available_until:
|
if sei.available_until:
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -221,7 +241,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'subevent': subevent.pk,
|
'subevent': subevent.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.subevents:write',
|
||||||
))
|
))
|
||||||
for sei in subevent.var_overrides.values():
|
for sei in subevent.var_overrides.values():
|
||||||
if sei.available_from:
|
if sei.available_from:
|
||||||
@@ -234,7 +255,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'subevent': subevent.pk,
|
'subevent': subevent.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.subevents:write',
|
||||||
))
|
))
|
||||||
if sei.available_until:
|
if sei.available_until:
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -246,7 +268,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'subevent': subevent.pk,
|
'subevent': subevent.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.subevents:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
for d in event.discounts.filter(Q(available_from__isnull=False) | Q(available_until__isnull=False)):
|
for d in event.discounts.filter(Q(available_from__isnull=False) | Q(available_until__isnull=False)):
|
||||||
@@ -259,7 +282,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'discount': d.pk,
|
'discount': d.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
if d.available_until:
|
if d.available_until:
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -270,7 +294,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'discount': d.pk,
|
'discount': d.pk,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
for p in event.items.filter(Q(available_from__isnull=False) | Q(available_until__isnull=False)):
|
for p in event.items.filter(Q(available_from__isnull=False) | Q(available_until__isnull=False)):
|
||||||
@@ -283,7 +308,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'item': p.pk,
|
'item': p.pk,
|
||||||
}) + '#id_available_from_0'
|
}) + '#id_available_from_0',
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
if p.available_until:
|
if p.available_until:
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -294,7 +320,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'item': p.pk,
|
'item': p.pk,
|
||||||
}) + '#id_available_until_0'
|
}) + '#id_available_until_0',
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
for v in ItemVariation.objects.filter(
|
for v in ItemVariation.objects.filter(
|
||||||
@@ -313,7 +340,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'item': v.item.pk,
|
'item': v.item.pk,
|
||||||
}) + '#tab-0-3-open'
|
}) + '#tab-0-3-open',
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
if v.available_until:
|
if v.available_until:
|
||||||
tl.append(TimelineEvent(
|
tl.append(TimelineEvent(
|
||||||
@@ -327,7 +355,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'item': v.item.pk,
|
'item': v.item.pk,
|
||||||
}) + '#tab-0-3-open'
|
}) + '#tab-0-3-open',
|
||||||
|
edit_permission='event.items:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
pprovs = event.get_payment_providers()
|
pprovs = event.get_payment_providers()
|
||||||
@@ -357,7 +386,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'provider': pprov.identifier,
|
'provider': pprov.identifier,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.payment:write',
|
||||||
))
|
))
|
||||||
availability_date = pprov.settings.get('_availability_date', as_type=RelativeDateWrapper)
|
availability_date = pprov.settings.get('_availability_date', as_type=RelativeDateWrapper)
|
||||||
if availability_date:
|
if availability_date:
|
||||||
@@ -375,7 +405,8 @@ def timeline_for_event(event, subevent=None):
|
|||||||
'event': event.slug,
|
'event': event.slug,
|
||||||
'organizer': event.organizer.slug,
|
'organizer': event.organizer.slug,
|
||||||
'provider': pprov.identifier,
|
'provider': pprov.identifier,
|
||||||
})
|
}),
|
||||||
|
edit_permission='event.settings.payment:write',
|
||||||
))
|
))
|
||||||
|
|
||||||
for recv, resp in timeline_events.send(sender=event, subevent=subevent):
|
for recv, resp in timeline_events.send(sender=event, subevent=subevent):
|
||||||
|
|||||||
@@ -43,24 +43,29 @@ def get_event_navigation(request: HttpRequest):
|
|||||||
'icon': 'dashboard',
|
'icon': 'dashboard',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
if 'event.settings.general:write' in request.eventpermset:
|
event_settings = []
|
||||||
event_settings = [
|
if "event.settings.general:write" in request.eventpermset:
|
||||||
{
|
event_settings.append({
|
||||||
'label': _('General'),
|
'label': _('General'),
|
||||||
'url': reverse('control:event.settings', kwargs={
|
'url': reverse('control:event.settings', kwargs={
|
||||||
'event': request.event.slug,
|
'event': request.event.slug,
|
||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
}),
|
}),
|
||||||
'active': url.url_name == 'event.settings',
|
'active': url.url_name == 'event.settings',
|
||||||
},
|
})
|
||||||
{
|
|
||||||
'label': _('Payment'),
|
if "event.settings.payment:write" in request.eventpermset or "event.settings.general:write" in request.eventpermset:
|
||||||
'url': reverse('control:event.settings.payment', kwargs={
|
event_settings.append({
|
||||||
'event': request.event.slug,
|
'label': _('Payment'),
|
||||||
'organizer': request.event.organizer.slug,
|
'url': reverse('control:event.settings.payment', kwargs={
|
||||||
}),
|
'event': request.event.slug,
|
||||||
'active': url.url_name in ('event.settings.payment', 'event.settings.payment.provider'),
|
'organizer': request.event.organizer.slug,
|
||||||
},
|
}),
|
||||||
|
'active': url.url_name in ('event.settings.payment', 'event.settings.payment.provider'),
|
||||||
|
})
|
||||||
|
|
||||||
|
if "event.settings.general:write" in request.eventpermset:
|
||||||
|
event_settings += [
|
||||||
{
|
{
|
||||||
'label': _('Plugins'),
|
'label': _('Plugins'),
|
||||||
'url': reverse('control:event.settings.plugins', kwargs={
|
'url': reverse('control:event.settings.plugins', kwargs={
|
||||||
@@ -84,23 +89,31 @@ def get_event_navigation(request: HttpRequest):
|
|||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
}),
|
}),
|
||||||
'active': url.url_name == 'event.settings.mail',
|
'active': url.url_name == 'event.settings.mail',
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
'label': _('Taxes'),
|
|
||||||
'url': reverse('control:event.settings.tax', kwargs={
|
if "event.settings.tax:write" in request.eventpermset or "event.settings.general:write" in request.eventpermset:
|
||||||
'event': request.event.slug,
|
event_settings.append({
|
||||||
'organizer': request.event.organizer.slug,
|
'label': _('Taxes'),
|
||||||
}),
|
'url': reverse('control:event.settings.tax', kwargs={
|
||||||
'active': url.url_name.startswith('event.settings.tax'),
|
'event': request.event.slug,
|
||||||
},
|
'organizer': request.event.organizer.slug,
|
||||||
{
|
}),
|
||||||
'label': _('Invoicing'),
|
'active': url.url_name.startswith('event.settings.tax'),
|
||||||
'url': reverse('control:event.settings.invoice', kwargs={
|
})
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
if "event.settings.invoicing:write" in request.eventpermset or "event.settings.general:write" in request.eventpermset:
|
||||||
}),
|
event_settings.append({
|
||||||
'active': url.url_name == 'event.settings.invoice',
|
'label': _('Invoicing'),
|
||||||
},
|
'url': reverse('control:event.settings.invoice', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': url.url_name == 'event.settings.invoice',
|
||||||
|
})
|
||||||
|
|
||||||
|
if "event.settings.general:write" in request.eventpermset:
|
||||||
|
event_settings += [
|
||||||
{
|
{
|
||||||
'label': pgettext_lazy('action', 'Cancellation'),
|
'label': pgettext_lazy('action', 'Cancellation'),
|
||||||
'url': reverse('control:event.settings.cancel', kwargs={
|
'url': reverse('control:event.settings.cancel', kwargs={
|
||||||
@@ -118,86 +131,85 @@ def get_event_navigation(request: HttpRequest):
|
|||||||
'active': url.url_name == 'event.settings.widget',
|
'active': url.url_name == 'event.settings.widget',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# It would be better to allow plugins to handle the permission themselves, but for backwards compatibility
|
||||||
|
# we need to have it in the "if" statement
|
||||||
event_settings += sorted(
|
event_settings += sorted(
|
||||||
sum((list(a[1]) for a in nav_event_settings.send(request.event, request=request)), []),
|
sum((list(a[1]) for a in nav_event_settings.send(request.event, request=request)), []),
|
||||||
key=lambda r: r['label']
|
key=lambda r: r['label']
|
||||||
)
|
)
|
||||||
|
if event_settings:
|
||||||
nav.append({
|
nav.append({
|
||||||
'label': _('Settings'),
|
'label': _('Settings'),
|
||||||
'url': reverse('control:event.settings', kwargs={
|
'url': event_settings[0]["url"],
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': False,
|
'active': False,
|
||||||
'icon': 'wrench',
|
'icon': 'wrench',
|
||||||
'children': event_settings
|
'children': event_settings
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'event.items:write' in request.eventpermset:
|
nav.append({
|
||||||
nav.append({
|
'label': _('Products'),
|
||||||
'label': _('Products'),
|
'url': reverse('control:event.items', kwargs={
|
||||||
'url': reverse('control:event.items', kwargs={
|
'event': request.event.slug,
|
||||||
'event': request.event.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
'organizer': request.event.organizer.slug,
|
}),
|
||||||
}),
|
'active': False,
|
||||||
'active': False,
|
'icon': 'ticket',
|
||||||
'icon': 'ticket',
|
'children': [
|
||||||
'children': [
|
{
|
||||||
{
|
'label': _('Products'),
|
||||||
'label': _('Products'),
|
'url': reverse('control:event.items', kwargs={
|
||||||
'url': reverse('control:event.items', kwargs={
|
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': url.url_name in (
|
|
||||||
'event.item', 'event.items.add', 'event.items') or "event.item." in url.url_name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'label': _('Quotas'),
|
|
||||||
'url': reverse('control:event.items.quotas', kwargs={
|
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': 'event.items.quota' in url.url_name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'label': _('Categories'),
|
|
||||||
'url': reverse('control:event.items.categories', kwargs={
|
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': 'event.items.categories' in url.url_name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'label': _('Questions'),
|
|
||||||
'url': reverse('control:event.items.questions', kwargs={
|
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': 'event.items.questions' in url.url_name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'label': _('Discounts'),
|
|
||||||
'url': reverse('control:event.items.discounts', kwargs={
|
|
||||||
'event': request.event.slug,
|
|
||||||
'organizer': request.event.organizer.slug,
|
|
||||||
}),
|
|
||||||
'active': 'event.items.discounts' in url.url_name,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
if 'event.settings.general:write' in request.eventpermset:
|
|
||||||
if request.event.has_subevents:
|
|
||||||
nav.append({
|
|
||||||
'label': pgettext_lazy('subevent', 'Dates'),
|
|
||||||
'url': reverse('control:event.subevents', kwargs={
|
|
||||||
'event': request.event.slug,
|
'event': request.event.slug,
|
||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
}),
|
}),
|
||||||
'active': ('event.subevent' in url.url_name),
|
'active': url.url_name in (
|
||||||
'icon': 'calendar',
|
'event.item', 'event.items.add', 'event.items') or "event.item." in url.url_name,
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
'label': _('Quotas'),
|
||||||
|
'url': reverse('control:event.items.quotas', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': 'event.items.quota' in url.url_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Categories'),
|
||||||
|
'url': reverse('control:event.items.categories', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': 'event.items.categories' in url.url_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Questions'),
|
||||||
|
'url': reverse('control:event.items.questions', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': 'event.items.questions' in url.url_name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': _('Discounts'),
|
||||||
|
'url': reverse('control:event.items.discounts', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': 'event.items.discounts' in url.url_name,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
if request.event.has_subevents:
|
||||||
|
nav.append({
|
||||||
|
'label': pgettext_lazy('subevent', 'Dates'),
|
||||||
|
'url': reverse('control:event.subevents', kwargs={
|
||||||
|
'event': request.event.slug,
|
||||||
|
'organizer': request.event.organizer.slug,
|
||||||
|
}),
|
||||||
|
'active': ('event.subevent' in url.url_name),
|
||||||
|
'icon': 'calendar',
|
||||||
|
})
|
||||||
|
|
||||||
if 'event.orders:read' in request.eventpermset:
|
if 'event.orders:read' in request.eventpermset:
|
||||||
children = [
|
children = [
|
||||||
@@ -291,7 +303,7 @@ def get_event_navigation(request: HttpRequest):
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'event.orders:read' in request.eventpermset:
|
if 'event.orders:read' in request.eventpermset or 'event.settings.general:write' in request.eventpermset:
|
||||||
nav.append({
|
nav.append({
|
||||||
'label': pgettext_lazy('navigation', 'Check-in'),
|
'label': pgettext_lazy('navigation', 'Check-in'),
|
||||||
'url': reverse('control:event.orders.checkinlists', kwargs={
|
'url': reverse('control:event.orders.checkinlists', kwargs={
|
||||||
@@ -544,7 +556,7 @@ def get_organizer_navigation(request):
|
|||||||
'icon': 'group',
|
'icon': 'group',
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'organizer.giftcards:write' in request.orgapermset:
|
if 'organizer.giftcards:read' in request.orgapermset or 'organizer.giftcards:write' in request.orgapermset:
|
||||||
children = []
|
children = []
|
||||||
children.append({
|
children.append({
|
||||||
'label': _('Gift cards'),
|
'label': _('Gift cards'),
|
||||||
@@ -575,7 +587,7 @@ def get_organizer_navigation(request):
|
|||||||
|
|
||||||
if request.organizer.settings.customer_accounts:
|
if request.organizer.settings.customer_accounts:
|
||||||
children = []
|
children = []
|
||||||
if 'organizer.customers:write' in request.orgapermset:
|
if 'organizer.customers:read' in request.orgapermset or 'organizer.customers:write' in request.orgapermset:
|
||||||
children.append(
|
children.append(
|
||||||
{
|
{
|
||||||
'label': _('Customers'),
|
'label': _('Customers'),
|
||||||
@@ -624,16 +636,17 @@ def get_organizer_navigation(request):
|
|||||||
})
|
})
|
||||||
|
|
||||||
if request.organizer.settings.reusable_media_active:
|
if request.organizer.settings.reusable_media_active:
|
||||||
nav.append({
|
if 'organizer.reusablemedia:read' in request.orgapermset or 'organizer.reusablemedia:write' in request.orgapermset:
|
||||||
'label': _('Reusable media'),
|
nav.append({
|
||||||
'url': reverse('control:organizer.reusable_media', kwargs={
|
'label': _('Reusable media'),
|
||||||
'organizer': request.organizer.slug
|
'url': reverse('control:organizer.reusable_media', kwargs={
|
||||||
}),
|
'organizer': request.organizer.slug
|
||||||
'icon': 'key',
|
}),
|
||||||
'active': 'organizer.reusable_medi' in url.url_name,
|
'icon': 'key',
|
||||||
})
|
'active': 'organizer.reusable_medi' in url.url_name,
|
||||||
|
})
|
||||||
|
|
||||||
if 'organizer.settings.general:write' in request.orgapermset:
|
if 'organizer.devices:read' in request.orgapermset or 'organizer.devices:write' in request.orgapermset:
|
||||||
nav.append({
|
nav.append({
|
||||||
'label': _('Devices'),
|
'label': _('Devices'),
|
||||||
'url': reverse('control:organizer.devices', kwargs={
|
'url': reverse('control:organizer.devices', kwargs={
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ def event_permission_required(permission):
|
|||||||
This view decorator rejects all requests with a 403 response which are not from
|
This view decorator rejects all requests with a 403 response which are not from
|
||||||
users having the given permission for the event the request is associated with.
|
users having the given permission for the event the request is associated with.
|
||||||
"""
|
"""
|
||||||
if permission == 'event.settings.general:write':
|
if permission == 'can_change_settings':
|
||||||
# Legacy support
|
# Legacy support
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.general:write'
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new check-in list" %}
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new check-in list" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if can_change_organizer_settings %}
|
{% if link_device_settings %}
|
||||||
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}"
|
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}"
|
||||||
class="btn btn-default btn-lg"><i class="fa fa-tablet"></i> {% trans "Connected devices" %}</a>
|
class="btn btn-default btn-lg"><i class="fa fa-tablet"></i> {% trans "Connected devices" %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -79,11 +79,11 @@
|
|||||||
<a href="{% url "control:event.orders.checkinlists.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
<a href="{% url "control:event.orders.checkinlists.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new check-in list" %}</a>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new check-in list" %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if can_change_organizer_settings %}
|
{% if link_device_settings %}
|
||||||
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}"
|
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}"
|
||||||
class="btn btn-default"><i class="fa fa-tablet"></i> {% trans "Connected devices" %}</a>
|
class="btn btn-default"><i class="fa fa-tablet"></i> {% trans "Connected devices" %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if "event.settings.general:write" in request.eventpermset %}
|
{% if "event.settings.general:write" in request.eventpermset and "event.orders:write" in request.eventpermset %}
|
||||||
<a href="{% url "control:event.orders.checkinlists.reset" organizer=request.event.organizer.slug event=request.event.slug %}"
|
<a href="{% url "control:event.orders.checkinlists.reset" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
class="btn btn-default">
|
class="btn btn-default">
|
||||||
<span class="fa fa-repeat"></span>
|
<span class="fa fa-repeat"></span>
|
||||||
@@ -100,7 +100,9 @@
|
|||||||
<a href="?{% url_replace request 'ordering' '-name' %}"><i class="fa fa-caret-down"></i></a>
|
<a href="?{% url_replace request 'ordering' '-name' %}"><i class="fa fa-caret-down"></i></a>
|
||||||
<a href="?{% url_replace request 'ordering' 'name' %}"><i class="fa fa-caret-up"></i></a>
|
<a href="?{% url_replace request 'ordering' 'name' %}"><i class="fa fa-caret-up"></i></a>
|
||||||
</th>
|
</th>
|
||||||
<th>{% trans "Checked in" %}</th>
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
|
<th>{% trans "Checked in" %}</th>
|
||||||
|
{% endif %}
|
||||||
{% if request.event.has_subevents %}
|
{% if request.event.has_subevents %}
|
||||||
<th>
|
<th>
|
||||||
{% trans "Date" context "subevent" %}
|
{% trans "Date" context "subevent" %}
|
||||||
@@ -119,18 +121,20 @@
|
|||||||
<strong><a
|
<strong><a
|
||||||
href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}">{{ cl.name }}</a></strong>
|
href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}">{{ cl.name }}</a></strong>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
<div class="quotabox availability">
|
<td>
|
||||||
<div class="progress">
|
<div class="quotabox availability">
|
||||||
<div class="progress-bar progress-bar-success progress-bar-{{ cl.percent }}">
|
<div class="progress">
|
||||||
|
<div class="progress-bar progress-bar-success progress-bar-{{ cl.percent }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="numbers">
|
||||||
|
{{ cl.checkin_count|default_if_none:"0" }} /
|
||||||
|
{{ cl.position_count|default_if_none:"0" }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="numbers">
|
</td>
|
||||||
{{ cl.checkin_count|default_if_none:"0" }} /
|
{% endif %}
|
||||||
{{ cl.position_count|default_if_none:"0" }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{% if request.event.has_subevents %}
|
{% if request.event.has_subevents %}
|
||||||
{% if cl.subevent %}
|
{% if cl.subevent %}
|
||||||
<td>
|
<td>
|
||||||
@@ -156,16 +160,18 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-eye"></i></a>
|
<a href="{% url "control:event.orders.checkinlists.show" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-eye"></i></a>
|
||||||
|
<a href="{% url "control:event.orders.checkinlists.simulator" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||||
|
title="{% trans "Check-in simulator" %}" data-toggle="tooltip"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-flask"></i></a>
|
||||||
|
{% endif %}
|
||||||
{% if "event.settings.general:write" in request.eventpermset %}
|
{% if "event.settings.general:write" in request.eventpermset %}
|
||||||
<a href="{% url "control:event.orders.checkinlists.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ cl.id }}"
|
<a href="{% url "control:event.orders.checkinlists.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ cl.id }}"
|
||||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||||
<span class="fa fa-copy"></span>
|
<span class="fa fa-copy"></span>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url "control:event.orders.checkinlists.simulator" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
|
||||||
title="{% trans "Check-in simulator" %}" data-toggle="tooltip"
|
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-flask"></i></a>
|
|
||||||
<a href="{% url "control:event.orders.checkinlists.edit" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
<a href="{% url "control:event.orders.checkinlists.edit" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
||||||
<a href="{% url "control:event.orders.checkinlists.delete" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
<a href="{% url "control:event.orders.checkinlists.delete" organizer=request.event.organizer.slug event=request.event.slug list=cl.id %}"
|
||||||
|
|||||||
@@ -11,18 +11,20 @@
|
|||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
{% for identifier, display_name, pending, objects in providers %}
|
{% for identifier, display_name, pending, objects in providers %}
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<form action="{% url "control:event.order.sync_job" organizer=event.organizer.slug event=event.slug code=order.code provider=identifier %}" method="post" class="form-inline pull-right">
|
{% if "event.orders:write" in request.eventpermset %}
|
||||||
{% csrf_token %}
|
<form action="{% url "control:event.order.sync_job" organizer=event.organizer.slug event=event.slug code=order.code provider=identifier %}" method="post" class="form-inline pull-right">
|
||||||
{% if pending %}
|
{% csrf_token %}
|
||||||
{% if pending.not_before > now or pending.need_manual_retry %}
|
{% if pending %}
|
||||||
<button type="submit" name="run_job_now" value="{{ pending.pk }}" class="btn btn-default"><i class="fa fa-refresh"></i> {% trans "Retry now" %}</button>
|
{% if pending.not_before > now or pending.need_manual_retry %}
|
||||||
|
<button type="submit" name="run_job_now" value="{{ pending.pk }}" class="btn btn-default"><i class="fa fa-refresh"></i> {% trans "Retry now" %}</button>
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" name="cancel_job" value="{{ pending.pk }}" class="btn btn-danger"><i class="fa fa-times"></i> {% trans "Cancel" %}</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class="btn btn-default"><i class="fa fa-refresh"></i> {% trans "Sync now" %}</button>
|
||||||
|
<input type="hidden" name="queue_sync" value="true">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<button type="submit" name="cancel_job" value="{{ pending.pk }}" class="btn btn-danger"><i class="fa fa-times"></i> {% trans "Cancel" %}</button>
|
</form>
|
||||||
{% else %}
|
{% endif %}
|
||||||
<button type="submit" class="btn btn-default"><i class="fa fa-refresh"></i> {% trans "Sync now" %}</button>
|
|
||||||
<input type="hidden" name="queue_sync" value="true">
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
<p><b>{{ display_name }}</b></p>
|
<p><b>{{ display_name }}</b></p>
|
||||||
{% if pending %}
|
{% if pending %}
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -40,12 +40,16 @@
|
|||||||
this option.
|
this option.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-3">
|
<div class="col-sm-12 col-md-3 text-center">
|
||||||
<a href="{% url "control:event.cancel" organizer=request.organizer.slug event=request.event.slug %}"
|
{% if "event:cancel" in request.eventpermset %}
|
||||||
class="btn btn-danger btn-block btn-lg">
|
<a href="{% url "control:event.cancel" organizer=request.organizer.slug event=request.event.slug %}"
|
||||||
<span class="fa fa-ban"></span>
|
class="btn btn-danger btn-block btn-lg">
|
||||||
{% trans "Cancel event" %}
|
<span class="fa fa-ban"></span>
|
||||||
</a>
|
{% trans "Cancel event" %}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{% trans "No permission" %}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<span class="{% if e.time < nearly_now %}text-muted{% endif %}">
|
<span class="{% if e.time < nearly_now %}text-muted{% endif %}">
|
||||||
{{ e.entry.description }}
|
{{ e.entry.description }}
|
||||||
</span>
|
</span>
|
||||||
{% if e.entry.edit_url %}
|
{% if e.entry.edit_url and e.entry.edit_permission in request.eventpermset %}
|
||||||
|
|
||||||
<a href="{{ e.entry.edit_url }}" class="text-muted">
|
<a href="{{ e.entry.edit_url }}" class="text-muted">
|
||||||
<span class="fa fa-edit"></span>
|
<span class="fa fa-edit"></span>
|
||||||
|
|||||||
@@ -155,22 +155,24 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
{% if "event.orders:read" in request.eventpermset or "event.orders:write" in request.eventpermset or "event.settings.general:write" in request.eventpermset or "event.items:write" in request.eventpermset %}
|
||||||
<div class="panel-heading">
|
<div class="panel panel-default">
|
||||||
<h3 class="panel-title">
|
<div class="panel-heading">
|
||||||
{% trans "Event logs" %}
|
<h3 class="panel-title">
|
||||||
</h3>
|
{% trans "Event logs" %}
|
||||||
</div>
|
</h3>
|
||||||
<ul class="list-group" id="logs_target">
|
</div>
|
||||||
<div class="logs-lazy-loading">
|
<ul class="list-group" id="logs_target">
|
||||||
<span class="fa fa-cog fa-4x"></span>
|
<div class="logs-lazy-loading">
|
||||||
|
<span class="fa fa-cog fa-4x"></span>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<a href="{% url "control:event.log" event=request.event.slug organizer=request.event.organizer.slug %}">
|
||||||
|
{% trans "Show more logs" %}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
|
||||||
<div class="panel-footer">
|
|
||||||
<a href="{% url "control:event.log" event=request.event.slug organizer=request.event.organizer.slug %}">
|
|
||||||
{% trans "Show more logs" %}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -165,13 +165,15 @@
|
|||||||
</p>
|
</p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group submit-group">
|
{% if "event.settings.invoicing:write" in request.eventpermset %}
|
||||||
<button type="submit" class="btn btn-default btn-lg" name="preview" value="preview" formtarget="_blank">
|
<div class="form-group submit-group">
|
||||||
{% trans "Save and show preview" %}
|
<button type="submit" class="btn btn-default btn-lg" name="preview" value="preview" formtarget="_blank">
|
||||||
</button>
|
{% trans "Save and show preview" %}
|
||||||
<button type="submit" class="btn btn-primary btn-save">
|
</button>
|
||||||
{% trans "Save" %}
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
</button>
|
{% trans "Save" %}
|
||||||
</div>
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -41,14 +41,17 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url 'control:event.settings.payment.provider' event=request.event.slug organizer=request.organizer.slug provider=provider.identifier %}"
|
{% if "event.settings.payment:write" in request.eventpermset %}
|
||||||
class="btn btn-default">
|
<a href="{% url 'control:event.settings.payment.provider' event=request.event.slug organizer=request.organizer.slug provider=provider.identifier %}"
|
||||||
<span class="fa fa-cog"></span>
|
class="btn btn-default">
|
||||||
{% trans "Settings" %}
|
<span class="fa fa-cog"></span>
|
||||||
</a>
|
{% trans "Settings" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if "event.settings.general:write" in request.eventpermset %}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4">
|
<td colspan="4">
|
||||||
<br>
|
<br>
|
||||||
@@ -58,6 +61,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@@ -83,10 +87,12 @@
|
|||||||
{% bootstrap_field form.payment_explanation layout="control" %}
|
{% bootstrap_field form.payment_explanation layout="control" %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group submit-group">
|
{% if "event.settings.payment:write" in request.eventpermset %}
|
||||||
<button type="submit" class="btn btn-primary btn-save">
|
<div class="form-group submit-group">
|
||||||
{% trans "Save" %}
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
</button>
|
{% trans "Save" %}
|
||||||
</div>
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -23,8 +23,10 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if "event.settings.tax:write" in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}</a>
|
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -42,10 +44,14 @@
|
|||||||
{% for tr in taxrules %}
|
{% for tr in taxrules %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<strong><a
|
{% if "event.settings.tax:write" in request.eventpermset %}
|
||||||
href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
<strong><a
|
||||||
{{ tr.internal_name|default:tr.name }}
|
href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
||||||
</a></strong>
|
{{ tr.internal_name|default:tr.name }}
|
||||||
|
</a></strong>
|
||||||
|
{% else %}
|
||||||
|
<strong>{{ tr.internal_name|default:tr.name }}</strong>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if tr.default %}
|
{% if tr.default %}
|
||||||
@@ -53,7 +59,7 @@
|
|||||||
<span class="fa fa-check"></span>
|
<span class="fa fa-check"></span>
|
||||||
{% trans "Default" %}
|
{% trans "Default" %}
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
{% elif "event.settings.tax:write" in request.eventpermset %}
|
||||||
<form class="form-inline" method="post"
|
<form class="form-inline" method="post"
|
||||||
action="{% url "control:event.settings.tax.default" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
action="{% url "control:event.settings.tax.default" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -83,10 +89,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}"
|
{% if "event.settings.tax:write" in request.eventpermset %}
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<a href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}"
|
||||||
<a href="{% url "control:event.settings.tax.delete" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}"
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.settings.tax.delete" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}"
|
||||||
|
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -94,9 +102,11 @@
|
|||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5">
|
<td colspan="5">
|
||||||
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if "event.settings.tax:write" in request.eventpermset %}
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}
|
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
</a>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
@@ -111,10 +121,12 @@
|
|||||||
{% bootstrap_field form.tax_rounding layout="control" %}
|
{% bootstrap_field form.tax_rounding layout="control" %}
|
||||||
{% bootstrap_field form.display_net_prices layout="control" %}
|
{% bootstrap_field form.display_net_prices layout="control" %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div class="form-group submit-group">
|
{% if "event.settings.tax:write" in request.eventpermset %}
|
||||||
<button type="submit" class="btn btn-primary btn-save">
|
<div class="form-group submit-group">
|
||||||
{% trans "Save" %}
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
</button>
|
{% trans "Save" %}
|
||||||
</div>
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -16,14 +16,18 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new category" %}</a>
|
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new category" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new category" %}
|
<p>
|
||||||
</a>
|
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new category" %}
|
||||||
</p>
|
</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -39,7 +43,11 @@
|
|||||||
{% for c in categories %}
|
{% for c in categories %}
|
||||||
<tr data-dnd-id="{{ c.id }}">
|
<tr data-dnd-id="{{ c.id }}">
|
||||||
<td>
|
<td>
|
||||||
<strong><a href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}">{{ c.internal_name|default:c.name }}</a></strong>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<strong><a href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}">{{ c.internal_name|default:c.name }}</a></strong>
|
||||||
|
{% else %}
|
||||||
|
<strong>{{ c.internal_name|default:c.name }}</strong>
|
||||||
|
{% endif %}
|
||||||
<br>
|
<br>
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
#{{ c.pk }}
|
#{{ c.pk }}
|
||||||
@@ -49,15 +57,17 @@
|
|||||||
{{ c.get_category_type_display }}
|
{{ c.get_category_type_display }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<button title="{% trans "Move up" %}" formaction="{% url "control:event.items.categories.up" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm sortable-up"{% if forloop.counter0 == 0 and not page_obj.has_previous %} disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<button title="{% trans "Move down" %}" formaction="{% url "control:event.items.categories.down" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm sortable-down"{% if forloop.revcounter0 == 0 and not page_obj.has_next %} disabled{% endif %}><i class="fa fa-arrow-down"></i></button>
|
<button title="{% trans "Move up" %}" formaction="{% url "control:event.items.categories.up" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm sortable-up"{% if forloop.counter0 == 0 and not page_obj.has_previous %} disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
||||||
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
<button title="{% trans "Move down" %}" formaction="{% url "control:event.items.categories.down" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm sortable-down"{% if forloop.revcounter0 == 0 and not page_obj.has_next %} disabled{% endif %}><i class="fa fa-arrow-down"></i></button>
|
||||||
<a title="{% trans "Edit" %}" href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
||||||
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ c.id }}"
|
<a title="{% trans "Edit" %}" href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
<a href="{% url "control:event.items.categories.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ c.id }}"
|
||||||
<span class="fa fa-copy"></span>
|
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||||
</a>
|
<span class="fa fa-copy"></span>
|
||||||
<a title="{% trans "Delete" %}" href="{% url "control:event.items.categories.delete" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
</a>
|
||||||
|
<a title="{% trans "Delete" %}" href="{% url "control:event.items.categories.delete" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -39,15 +39,19 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new discount" %}</a>
|
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new discount" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new discount" %}
|
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
</a>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new discount" %}
|
||||||
</p>
|
</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -70,8 +74,12 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<del>
|
<del>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url "control:event.items.discounts.edit" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}">
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.items.discounts.edit" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}">
|
||||||
{{ d.internal_name }}</a>
|
{{ d.internal_name }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ d.internal_name }}
|
||||||
|
{% endif %}
|
||||||
{% if d.active %}
|
{% if d.active %}
|
||||||
</strong>
|
</strong>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -134,23 +142,25 @@
|
|||||||
</td>
|
</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<button formaction="{% url "control:event.items.discounts.up" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-default btn-sm sortable-up" title="{% trans "Move up" %}"
|
<button formaction="{% url "control:event.items.discounts.up" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
||||||
{% if forloop.counter0 == 0 and not page_obj.has_previous %}
|
class="btn btn-default btn-sm sortable-up" title="{% trans "Move up" %}"
|
||||||
disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
{% if forloop.counter0 == 0 and not page_obj.has_previous %}
|
||||||
<button formaction="{% url "control:event.items.discounts.down" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
||||||
class="btn btn-default btn-sm sortable-down" title="{% trans "Move down" %}"
|
<button formaction="{% url "control:event.items.discounts.down" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
||||||
{% if forloop.revcounter0 == 0 and not page_obj.has_next %} disabled{% endif %}>
|
class="btn btn-default btn-sm sortable-down" title="{% trans "Move down" %}"
|
||||||
<i class="fa fa-arrow-down"></i></button>
|
{% if forloop.revcounter0 == 0 and not page_obj.has_next %} disabled{% endif %}>
|
||||||
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
<i class="fa fa-arrow-down"></i></button>
|
||||||
<a href="{% url "control:event.items.discounts.edit" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<a href="{% url "control:event.items.discounts.edit" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
||||||
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ d.id }}"
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
<a href="{% url "control:event.items.discounts.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ d.id }}"
|
||||||
<span class="fa fa-copy"></span>
|
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||||
</a>
|
<span class="fa fa-copy"></span>
|
||||||
<a href="{% url "control:event.items.discounts.delete" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
</a>
|
||||||
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.items.discounts.delete" organizer=request.event.organizer.slug event=request.event.slug discount=d.id %}"
|
||||||
|
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -21,14 +21,18 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new product" %}</a>
|
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new product" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new product" %}</a>
|
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
</p>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new product" %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -51,7 +55,9 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr class="sortable-disabled"><th colspan="9" scope="colgroup" class="text-muted">
|
<tr class="sortable-disabled"><th colspan="9" scope="colgroup" class="text-muted">
|
||||||
{{ c.internal_name|default:c.name }}{% if c.category_type != "normal" %} <span class="font-normal">({{ c.get_category_type_display }})</span>{% endif %}
|
{{ c.internal_name|default:c.name }}{% if c.category_type != "normal" %} <span class="font-normal">({{ c.get_category_type_display }})</span>{% endif %}
|
||||||
<a href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" title="{% trans "Edit" %}"><span class="fa fa-edit fa-fw"></span></a>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.items.categories.edit" organizer=request.event.organizer.slug event=request.event.slug category=c.id %}" title="{% trans "Edit" %}"><span class="fa fa-edit fa-fw"></span></a>
|
||||||
|
{% endif %}
|
||||||
</th></tr>
|
</th></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -62,7 +68,11 @@
|
|||||||
<tr data-dnd-id="{{ i.id }}" {% if not i.active %}class="row-muted"{% endif %}>
|
<tr data-dnd-id="{{ i.id }}" {% if not i.active %}class="row-muted"{% endif %}>
|
||||||
<td><strong>
|
<td><strong>
|
||||||
{% if not i.active %}<strike>{% endif %}
|
{% if not i.active %}<strike>{% endif %}
|
||||||
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}">{{ i }}</a>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}">{{ i }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ i }}
|
||||||
|
{% endif %}
|
||||||
{% if not i.active %}</strike>{% endif %}
|
{% if not i.active %}</strike>{% endif %}
|
||||||
</strong>
|
</strong>
|
||||||
<br>
|
<br>
|
||||||
@@ -158,12 +168,14 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip col-actions">
|
<td class="text-right flip col-actions">
|
||||||
<button title="{% trans "Move up" %}" formaction="{% url "control:event.items.up" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm sortable-up"{% if forloop.counter0 == 0 %} disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<button title="{% trans "Move down" %}" formaction="{% url "control:event.items.down" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm sortable-down"{% if forloop.revcounter0 == 0 %} disabled{% endif %}><i class="fa fa-arrow-down"></i></button>
|
<button title="{% trans "Move up" %}" formaction="{% url "control:event.items.up" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm sortable-up"{% if forloop.counter0 == 0 %} disabled{% endif %}><i class="fa fa-arrow-up"></i></button>
|
||||||
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
<button title="{% trans "Move down" %}" formaction="{% url "control:event.items.down" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm sortable-down"{% if forloop.revcounter0 == 0 %} disabled{% endif %}><i class="fa fa-arrow-down"></i></button>
|
||||||
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm" title="{% trans "Edit" %}"><i class="fa fa-edit"></i></a>
|
<span class="dnd-container" title="{% trans "Click and drag this button to reorder. Double click to show buttons for reordering." %}"></span>
|
||||||
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ i.id }}" class="btn btn-default btn-sm" title="{% trans "Clone" %}" data-toggle="tooltip"><i class="fa fa-copy"></i></a>
|
<a href="{% url "control:event.item" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-default btn-sm" title="{% trans "Edit" %}"><i class="fa fa-edit"></i></a>
|
||||||
<a href="{% url "control:event.items.delete" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-danger btn-sm" title="{% trans "Delete" %}"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.items.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ i.id }}" class="btn btn-default btn-sm" title="{% trans "Clone" %}" data-toggle="tooltip"><i class="fa fa-copy"></i></a>
|
||||||
|
<a href="{% url "control:event.items.delete" organizer=request.event.organizer.slug event=request.event.slug item=i.id %}" class="btn btn-danger btn-sm" title="{% trans "Delete" %}"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -7,45 +7,57 @@
|
|||||||
{% block inside %}
|
{% block inside %}
|
||||||
<h1>
|
<h1>
|
||||||
{% blocktrans with name=question.question %}Question: {{ name }}{% endblocktrans %}
|
{% blocktrans with name=question.question %}Question: {{ name }}{% endblocktrans %}
|
||||||
<a href="{% url "control:event.items.questions.edit" event=request.event.slug organizer=request.event.organizer.slug question=question.pk %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-default">
|
<a href="{% url "control:event.items.questions.edit" event=request.event.slug organizer=request.event.organizer.slug question=question.pk %}"
|
||||||
<span class="fa fa-edit"></span>
|
class="btn btn-default">
|
||||||
{% trans "Edit question" %}
|
<span class="fa fa-edit"></span>
|
||||||
</a>
|
{% trans "Edit question" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div class="panel panel-default">
|
{% if 'event.orders:read' in request.eventpermset %}
|
||||||
<div class="panel-heading">
|
<div class="panel panel-default">
|
||||||
<h3 class="panel-title">{% trans "Filter" %}</h3>
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{% trans "Filter" %}</h3>
|
||||||
|
</div>
|
||||||
|
<form class="panel-body filter-form" action="" method="get">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2 col-xs-6">
|
||||||
|
{% bootstrap_field form.status %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
{% bootstrap_field form.item %}
|
||||||
|
</div>
|
||||||
|
{% if has_subevents %}
|
||||||
|
<div class="col-md-3 col-xs-6">
|
||||||
|
{% bootstrap_field form.subevent %}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 col-xs-6">
|
||||||
|
{% bootstrap_field form.date_range %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<button class="btn btn-primary btn-lg" type="submit">
|
||||||
|
<span class="fa fa-filter"></span>
|
||||||
|
{% trans "Filter" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<form class="panel-body filter-form" action="" method="get">
|
{% endif %}
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-2 col-xs-6">
|
|
||||||
{% bootstrap_field form.status %}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3 col-xs-6">
|
|
||||||
{% bootstrap_field form.item %}
|
|
||||||
</div>
|
|
||||||
{% if has_subevents %}
|
|
||||||
<div class="col-md-3 col-xs-6">
|
|
||||||
{% bootstrap_field form.subevent %}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4 col-xs-6">
|
|
||||||
{% bootstrap_field form.date_range %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="text-right">
|
|
||||||
<button class="btn btn-primary btn-lg" type="submit">
|
|
||||||
<span class="fa fa-filter"></span>
|
|
||||||
{% trans "Filter" %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if not stats %}
|
{% if 'event.orders:read' not in request.eventpermset %}
|
||||||
|
<div class="empty-collection col-md-10 col-xs-12">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
No permission to view answers.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% elif not stats %}
|
||||||
<div class="empty-collection col-md-10 col-xs-12">
|
<div class="empty-collection col-md-10 col-xs-12">
|
||||||
<p>
|
<p>
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new question" %}
|
<p>
|
||||||
</a>
|
<a href="{% url "control:event.items.questions.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new question" %}
|
||||||
</p>
|
</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-quotas">
|
<table class="table table-hover table-quotas">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -24,7 +26,9 @@
|
|||||||
<th class="iconcol"></th>
|
<th class="iconcol"></th>
|
||||||
<th class="iconcol"></th>
|
<th class="iconcol"></th>
|
||||||
<th>{% trans "Products" %}</th>
|
<th>{% trans "Products" %}</th>
|
||||||
<th class="action-col-2"></th>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
|
<th class="action-col-2"></th>
|
||||||
|
{% endif %}
|
||||||
<th class="action-col-2"></th>
|
<th class="action-col-2"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -79,16 +83,22 @@
|
|||||||
<small>{% trans "All personalized products" %}</small>
|
<small>{% trans "All personalized products" %}</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="dnd-container">
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
</td>
|
<td class="dnd-container">
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
{% if q.pk %}
|
{% if q.pk %}
|
||||||
<a href="{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-bar-chart"></i></a>
|
<a href="{% url "control:event.items.questions.show" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-bar-chart"></i></a>
|
||||||
<a href="{% url "control:event.items.questions.edit" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.questions.delete" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.items.questions.edit" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
|
<a href="{% url "control:event.items.questions.delete" organizer=request.event.organizer.slug event=request.event.slug question=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url "control:event.settings" organizer=request.event.organizer.slug event=request.event.slug %}#tab-0-2-open"
|
{% if 'event.settings.general:write' in request.eventpermset %}
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
<a href="{% url "control:event.settings" organizer=request.event.organizer.slug event=request.event.slug %}#tab-0-2-open"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-wrench"></i></a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -30,14 +30,18 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}</a>
|
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}
|
<p>
|
||||||
</a>
|
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new quota" %}
|
||||||
</p>
|
</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-quotas">
|
<table class="table table-hover table-quotas">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -91,12 +95,14 @@
|
|||||||
<td>{% if q.size == None %}Unlimited{% else %}{{ q.size }}{% endif %}</td>
|
<td>{% if q.size == None %}Unlimited{% else %}{{ q.size }}{% endif %}</td>
|
||||||
<td>{% include "pretixcontrol/items/fragment_quota_availability.html" with availability=q.cached_avail closed=q.closed %}</td>
|
<td>{% include "pretixcontrol/items/fragment_quota_availability.html" with availability=q.cached_avail closed=q.closed %}</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
{% if 'event.items:write' in request.eventpermset %}
|
||||||
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ q.id }}"
|
<a href="{% url "control:event.items.quotas.edit" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
<a href="{% url "control:event.items.quotas.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ q.id }}"
|
||||||
<span class="fa fa-copy"></span>
|
class="btn btn-sm btn-default" title="{% trans "Clone" %}" data-toggle="tooltip">
|
||||||
</a>
|
<span class="fa fa-copy"></span>
|
||||||
<a href="{% url "control:event.items.quotas.delete" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
</a>
|
||||||
|
<a href="{% url "control:event.items.quotas.delete" organizer=request.event.organizer.slug event=request.event.slug quota=q.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -319,7 +319,7 @@
|
|||||||
<span class="fa fa-check text-success fa-stack-1x fa-stack-shifted"></span>
|
<span class="fa fa-check text-success fa-stack-1x fa-stack-shifted"></span>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if i.transmission_status != "inflight" %}
|
{% if i.transmission_status != "inflight" and "event.orders:write" in request.eventpermset %}
|
||||||
<form class="form-inline helper-display-inline" method="post"
|
<form class="form-inline helper-display-inline" method="post"
|
||||||
action="{% url "control:event.order.retransmitinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
action="{% url "control:event.order.retransmitinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not i.canceled %}
|
{% if not i.canceled %}
|
||||||
{% if i.regenerate_allowed %}
|
{% if i.regenerate_allowed and "event.orders:write" in request.eventpermset %}
|
||||||
<form class="form-inline helper-display-inline" method="post"
|
<form class="form-inline helper-display-inline" method="post"
|
||||||
action="{% url "control:event.order.regeninvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
action="{% url "control:event.order.regeninvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
@@ -344,7 +344,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not i.is_cancellation %}
|
{% if not i.is_cancellation and "event.orders:write" in request.eventpermset %}
|
||||||
<form class="form-inline helper-display-inline" method="post"
|
<form class="form-inline helper-display-inline" method="post"
|
||||||
action="{% url "control:event.order.reissueinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
action="{% url "control:event.order.reissueinvoice" event=request.event.slug organizer=request.event.organizer.slug code=order.code id=i.pk %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|||||||
@@ -100,28 +100,30 @@
|
|||||||
{{ r.amount|money:request.event.currency }}
|
{{ r.amount|money:request.event.currency }}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
{% if r.state == "transit" or r.state == "created" %}
|
{% if "event.orders:write" in request.eventpermset %}
|
||||||
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
{% if r.state == "transit" or r.state == "created" %}
|
||||||
class="btn btn-danger btn-xs" data-toggle="tooltip">
|
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
||||||
<span class="fa fa-times"></span>
|
class="btn btn-danger btn-xs" data-toggle="tooltip">
|
||||||
{% trans "Cancel" %}
|
<span class="fa fa-times"></span>
|
||||||
</a>
|
{% trans "Cancel" %}
|
||||||
<a href="{% url "control:event.order.refunds.done" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
</a>
|
||||||
class="btn btn-primary btn-xs" data-toggle="tooltip">
|
<a href="{% url "control:event.order.refunds.done" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
||||||
<span class="fa fa-check"></span>
|
class="btn btn-primary btn-xs" data-toggle="tooltip">
|
||||||
{% trans "Confirm as done" %}
|
<span class="fa fa-check"></span>
|
||||||
</a>
|
{% trans "Confirm as done" %}
|
||||||
|
</a>
|
||||||
{% elif r.state == "external" %}
|
{% elif r.state == "external" %}
|
||||||
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
<a href="{% url "control:event.order.refunds.cancel" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
||||||
class="btn btn-default btn-xs" data-toggle="tooltip">
|
class="btn btn-default btn-xs" data-toggle="tooltip">
|
||||||
<span class="fa fa-times"></span>
|
<span class="fa fa-times"></span>
|
||||||
{% trans "Ignore" %}
|
{% trans "Ignore" %}
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url "control:event.order.refunds.process" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
<a href="{% url "control:event.order.refunds.process" event=request.event.slug organizer=request.event.organizer.slug code=r.order.code refund=r.pk %}?next={{ request.get_full_path|urlencode }}"
|
||||||
class="btn btn-primary btn-xs" data-toggle="tooltip">
|
class="btn btn-primary btn-xs" data-toggle="tooltip">
|
||||||
<span class="fa fa-check"></span>
|
<span class="fa fa-check"></span>
|
||||||
{% trans "Process refund" %}
|
{% trans "Process refund" %}
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -93,16 +93,18 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</dl>
|
</dl>
|
||||||
</form>
|
</form>
|
||||||
<div class="text-right">
|
{% if "organizer.customers:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.customer.edit" organizer=request.organizer.slug customer=customer.identifier %}"
|
<div class="text-right">
|
||||||
class="btn btn-default">
|
<a href="{% url "control:organizer.customer.edit" organizer=request.organizer.slug customer=customer.identifier %}"
|
||||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
class="btn btn-default">
|
||||||
</a>
|
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||||
<a href="{% url "control:organizer.customer.anonymize" organizer=request.organizer.slug customer=customer.identifier %}"
|
</a>
|
||||||
class="btn btn-danger">
|
<a href="{% url "control:organizer.customer.anonymize" organizer=request.organizer.slug customer=customer.identifier %}"
|
||||||
<i class="fa fa-trash"></i> {% trans "Anonymize" %}
|
class="btn btn-danger">
|
||||||
</a>
|
<i class="fa fa-trash"></i> {% trans "Anonymize" %}
|
||||||
</div>
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default items">
|
<div class="panel panel-default items">
|
||||||
@@ -162,35 +164,39 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:organizer.customer.membership.edit" organizer=request.organizer.slug customer=customer.identifier id=m.pk %}"
|
{% if "organizer.customers:write" in request.orgapermset %}
|
||||||
data-toggle="tooltip"
|
<a href="{% url "control:organizer.customer.membership.edit" organizer=request.organizer.slug customer=customer.identifier id=m.pk %}"
|
||||||
title="{% trans "Edit" %}"
|
|
||||||
class="btn btn-default">
|
|
||||||
<i class="fa fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
{% if m.testmode %}
|
|
||||||
<a href="{% url "control:organizer.customer.membership.delete" organizer=request.organizer.slug customer=customer.identifier id=m.pk %}"
|
|
||||||
data-toggle="tooltip"
|
data-toggle="tooltip"
|
||||||
title="{% trans "Delete" %}"
|
title="{% trans "Edit" %}"
|
||||||
class="btn btn-danger">
|
class="btn btn-default">
|
||||||
<i class="fa fa-trash"></i>
|
<i class="fa fa-edit"></i>
|
||||||
</a>
|
</a>
|
||||||
|
{% if m.testmode %}
|
||||||
|
<a href="{% url "control:organizer.customer.membership.delete" organizer=request.organizer.slug customer=customer.identifier id=m.pk %}"
|
||||||
|
data-toggle="tooltip"
|
||||||
|
title="{% trans "Delete" %}"
|
||||||
|
class="btn btn-danger">
|
||||||
|
<i class="fa fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
{% if "organizer.customers:write" in request.orgapermset %}
|
||||||
<tr>
|
<tfoot>
|
||||||
<td colspan="7">
|
<tr>
|
||||||
<a href="{% url "control:organizer.customer.membership.add" organizer=request.organizer.slug customer=customer.identifier %}"
|
<td colspan="7">
|
||||||
class="btn btn-default">
|
<a href="{% url "control:organizer.customer.membership.add" organizer=request.organizer.slug customer=customer.identifier %}"
|
||||||
<i class="fa fa-plus"></i>
|
class="btn btn-default">
|
||||||
{% trans "Add membership" %}
|
<i class="fa fa-plus"></i>
|
||||||
</a>
|
{% trans "Add membership" %}
|
||||||
</td>
|
</a>
|
||||||
</tr>
|
</td>
|
||||||
</tfoot>
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default items">
|
<div class="panel panel-default items">
|
||||||
@@ -300,14 +306,18 @@
|
|||||||
{% for gc in gift_cards %}
|
{% for gc in gift_cards %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url "control:organizer.giftcard" organizer=organizer.slug giftcard=gc.id %}">
|
{% if "organizer.giftcards:read" in request.orgapermset %}
|
||||||
<strong>{{ gc.secret }}</strong></a>
|
<a href="{% url "control:organizer.giftcard" organizer=organizer.slug giftcard=gc.id %}">
|
||||||
{% if gc.testmode %}
|
<strong>{{ gc.secret }}</strong></a>
|
||||||
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
{% else %}
|
||||||
{% endif %}
|
<strong>{{ gc.secret|slice:":3" }}…</strong>
|
||||||
{% if gc.expired %}
|
{% endif %}
|
||||||
<span class="label label-danger">{% trans "Expired" %}</span>
|
{% if gc.testmode %}
|
||||||
{% endif %}
|
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if gc.expired %}
|
||||||
|
<span class="label label-danger">{% trans "Expired" %}</span>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{{ gc.issuance|date:"SHORT_DATETIME_FORMAT" }}</td>
|
<td>{{ gc.issuance|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||||
<td>{% if gc.expires %}{{ gc.expires|date:"SHORT_DATETIME_FORMAT" }}{% endif %}</td>
|
<td>{% if gc.expires %}{{ gc.expires|date:"SHORT_DATETIME_FORMAT" }}{% endif %}</td>
|
||||||
@@ -316,10 +326,12 @@
|
|||||||
<p class="text-right">{{ gc.value|money:gc.currency }}</p>
|
<p class="text-right">{{ gc.value|money:gc.currency }}</p>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<a href="{% url "control:organizer.giftcard" organizer=organizer.slug giftcard=gc.id %}"
|
{% if "organizer.giftcards:read" in request.orgapermset %}
|
||||||
class="btn btn-default btn-sm" data-toggle="tooltip" title="{% trans "Details" %}">
|
<a href="{% url "control:organizer.giftcard" organizer=organizer.slug giftcard=gc.id %}"
|
||||||
<i class="fa fa-eye"></i>
|
class="btn btn-default btn-sm" data-toggle="tooltip" title="{% trans "Details" %}">
|
||||||
</a>
|
<i class="fa fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
No customer accounts have been created yet.
|
No customer accounts have been created yet.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
<a href="{% url "control:organizer.customer.create" organizer=request.organizer.slug %}"
|
{% if "organizer.customers:write" in request.orgapermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new customer" %}</a>
|
<a href="{% url "control:organizer.customer.create" organizer=request.organizer.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new customer" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
@@ -43,10 +45,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
{% if "organizer.customers:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.customer.create" organizer=request.organizer.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new customer" %}</a>
|
<a href="{% url "control:organizer.customer.create" organizer=request.organizer.slug %}"
|
||||||
</p>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new customer" %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -51,10 +51,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.device.add" organizer=request.organizer.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Connect a device" %}</a>
|
<a href="{% url "control:organizer.device.add" organizer=request.organizer.slug %}"
|
||||||
</p>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Connect a device" %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<form action="{% url "control:organizer.device.bulk_edit" organizer=request.organizer.slug %}" method="post">
|
<form action="{% url "control:organizer.device.bulk_edit" organizer=request.organizer.slug %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% for field in filter_form %}
|
{% for field in filter_form %}
|
||||||
@@ -64,10 +66,12 @@
|
|||||||
<table class="table table-condensed table-hover table-quotas">
|
<table class="table table-condensed table-hover table-quotas">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<label aria-label="{% trans "select all rows for batch-operation" %}"
|
<th>
|
||||||
class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
<label aria-label="{% trans "select all rows for batch-operation" %}"
|
||||||
</th>
|
class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||||
|
</th>
|
||||||
|
{% endif %}
|
||||||
<th>{% trans "Device ID" %}
|
<th>{% trans "Device ID" %}
|
||||||
<a href="?{% url_replace request 'ordering' '-device_id' %}"><i
|
<a href="?{% url_replace request 'ordering' '-device_id' %}"><i
|
||||||
class="fa fa-caret-down"></i></a>
|
class="fa fa-caret-down"></i></a>
|
||||||
@@ -105,12 +109,14 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for d in devices %}
|
{% for d in devices %}
|
||||||
<tr {% if d.revoked %}class="text-muted"{% endif %}>
|
<tr {% if d.revoked %}class="text-muted"{% endif %}>
|
||||||
<td>
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<label aria-label="{% trans "select row for batch-operation" %}"
|
<td>
|
||||||
class="batch-select-label"><input type="checkbox" name="device"
|
<label aria-label="{% trans "select row for batch-operation" %}"
|
||||||
class="batch-select-checkbox"
|
class="batch-select-label"><input type="checkbox" name="device"
|
||||||
value="{{ d.pk }}"/></label>
|
class="batch-select-checkbox"
|
||||||
</td>
|
value="{{ d.pk }}"/></label>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
<td>
|
<td>
|
||||||
{{ d.device_id }}
|
{{ d.device_id }}
|
||||||
</td>
|
</td>
|
||||||
@@ -158,15 +164,17 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
{% if not d.initialized %}
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.device.connect" organizer=request.organizer.slug device=d.id %}"
|
{% if not d.initialized %}
|
||||||
class="btn btn-primary btn-sm"><i class="fa fa-link"></i>
|
<a href="{% url "control:organizer.device.connect" organizer=request.organizer.slug device=d.id %}"
|
||||||
{% trans "Connect" %}</a>
|
class="btn btn-primary btn-sm"><i class="fa fa-link"></i>
|
||||||
{% endif %}
|
{% trans "Connect" %}</a>
|
||||||
{% if not d.initialized or d.api_token %}
|
{% endif %}
|
||||||
<a href="{% url "control:organizer.device.revoke" organizer=request.organizer.slug device=d.id %}"
|
{% if not d.initialized or d.api_token %}
|
||||||
class="btn btn-default btn-sm">
|
<a href="{% url "control:organizer.device.revoke" organizer=request.organizer.slug device=d.id %}"
|
||||||
{% trans "Revoke access" %}</a>
|
class="btn btn-default btn-sm">
|
||||||
|
{% trans "Revoke access" %}</a>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if d.initialized %}
|
{% if d.initialized %}
|
||||||
<a href="{% url "control:organizer.device.logs" organizer=request.organizer.slug device=d.id %}"
|
<a href="{% url "control:organizer.device.logs" organizer=request.organizer.slug device=d.id %}"
|
||||||
@@ -175,19 +183,23 @@
|
|||||||
{% trans "Logs" %}
|
{% trans "Logs" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url "control:organizer.device.edit" organizer=request.organizer.slug device=d.id %}"
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<a href="{% url "control:organizer.device.edit" organizer=request.organizer.slug device=d.id %}"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div class="batch-select-actions">
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<button type="submit" class="btn btn-primary btn-save" name="action" value="edit">
|
<div class="batch-select-actions">
|
||||||
<i class="fa fa-edit"></i>{% trans "Edit selected" %}
|
<button type="submit" class="btn btn-primary btn-save" name="action" value="edit">
|
||||||
</button>
|
<i class="fa fa-edit"></i>{% trans "Edit selected" %}
|
||||||
</div>
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
{% include "pretixcontrol/pagination.html" %}
|
{% include "pretixcontrol/pagination.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -6,10 +6,12 @@
|
|||||||
<p>
|
<p>
|
||||||
{% trans "The list below shows gates that you can use to group check-in devices." %}
|
{% trans "The list below shows gates that you can use to group check-in devices." %}
|
||||||
</p>
|
</p>
|
||||||
<a href="{% url "control:organizer.gate.add" organizer=request.organizer.slug %}" class="btn btn-default">
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
<span class="fa fa-plus"></span>
|
<a href="{% url "control:organizer.gate.add" organizer=request.organizer.slug %}" class="btn btn-default">
|
||||||
{% trans "Create a new gate" %}
|
<span class="fa fa-plus"></span>
|
||||||
</a>
|
{% trans "Create a new gate" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -21,15 +23,21 @@
|
|||||||
{% for g in gates %}
|
{% for g in gates %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>
|
<td><strong>
|
||||||
<a href="{% url "control:organizer.gate.edit" organizer=request.organizer.slug gate=g.id %}">
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
|
<a href="{% url "control:organizer.gate.edit" organizer=request.organizer.slug gate=g.id %}">
|
||||||
|
{{ g.name }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
{{ g.name }}
|
{{ g.name }}
|
||||||
</a>
|
{% endif %}
|
||||||
</strong></td>
|
</strong></td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:organizer.gate.edit" organizer=request.organizer.slug gate=g.id %}"
|
{% if "organizer.devices:write" in request.orgapermset %}
|
||||||
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
<a href="{% url "control:organizer.gate.edit" organizer=request.organizer.slug gate=g.id %}"
|
||||||
<a href="{% url "control:organizer.gate.delete" organizer=request.organizer.slug gate=g.id %}"
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:organizer.gate.delete" organizer=request.organizer.slug gate=g.id %}"
|
||||||
|
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@
|
|||||||
{% if card.testmode %}
|
{% if card.testmode %}
|
||||||
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
<span class="label label-warning">{% trans "TEST MODE" %}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{% url "control:organizer.giftcard.edit" organizer=request.organizer.slug giftcard=card.id %}"
|
{% if "organizer.giftcards:write" in request.orgapermset %}
|
||||||
class="btn btn-default">
|
<a href="{% url "control:organizer.giftcard.edit" organizer=request.organizer.slug giftcard=card.id %}"
|
||||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
class="btn btn-default">
|
||||||
</a>
|
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-10 col-xs-12">
|
<div class="col-md-10 col-xs-12">
|
||||||
@@ -112,22 +114,24 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
{% if "organizer.giftcards:write" in request.orgapermset %}
|
||||||
<tr>
|
<tfoot>
|
||||||
<td></td>
|
<tr>
|
||||||
<td>
|
<td></td>
|
||||||
<input type="text" class="form-control helper-display-block" placeholder="{% trans "Text" %}"
|
<td>
|
||||||
name="text">
|
<input type="text" class="form-control helper-display-block" placeholder="{% trans "Text" %}"
|
||||||
</td>
|
name="text">
|
||||||
<td class="text-right form-inline">
|
</td>
|
||||||
<input type="text" class="form-control input-sm" placeholder="{% trans "Value" %}" name="value">
|
<td class="text-right form-inline">
|
||||||
<button type="submit" class="btn btn-primary">
|
<input type="text" class="form-control input-sm" placeholder="{% trans "Value" %}" name="value">
|
||||||
<span class="fa fa-plus"></span>
|
<button type="submit" class="btn btn-primary">
|
||||||
</button>
|
<span class="fa fa-plus"></span>
|
||||||
</td>
|
</button>
|
||||||
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,10 +15,11 @@
|
|||||||
or you can manually issue gift cards.
|
or you can manually issue gift cards.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
{% if "organizer.giftcards:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
||||||
class="btn btn-default btn-lg"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}
|
class="btn btn-default btn-lg"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}
|
||||||
</a>
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
@@ -45,10 +46,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
{% if "organizer.giftcards:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}</a>
|
<a href="{% url "control:organizer.giftcard.add" organizer=request.organizer.slug %}"
|
||||||
</p>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Manually issue a gift card" %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
No media have been created yet.
|
No media have been created yet.
|
||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
{% if "organizer.reusablemedia:write" in request.orgapermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
@@ -40,10 +42,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
{% if "organizer.reusablemedia:write" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
<p>
|
||||||
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
<a href="{% url "control:organizer.reusable_medium.create" organizer=request.organizer.slug %}"
|
||||||
</p>
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new medium" %}</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -77,9 +81,13 @@
|
|||||||
{% if m.customer %}
|
{% if m.customer %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-user fa-fw"></span>
|
<span class="fa fa-user fa-fw"></span>
|
||||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=m.customer.identifier %}">
|
{% if "organizer.customers:read" in request.orgapermset %}
|
||||||
|
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=m.customer.identifier %}">
|
||||||
|
{{ m.customer }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
{{ m.customer }}
|
{{ m.customer }}
|
||||||
</a>
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if m.linked_orderposition %}
|
{% if m.linked_orderposition %}
|
||||||
@@ -92,8 +100,12 @@
|
|||||||
{% if m.linked_giftcard %}
|
{% if m.linked_giftcard %}
|
||||||
<span class="helper-display-block">
|
<span class="helper-display-block">
|
||||||
<span class="fa fa-credit-card fa-fw"></span>
|
<span class="fa fa-credit-card fa-fw"></span>
|
||||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=m.linked_giftcard.id %}">
|
{% if "organizer.giftcards:read" in request.orgapermset %}
|
||||||
{{ m.linked_giftcard.secret }}</a>
|
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=m.linked_giftcard.id %}">
|
||||||
|
{{ m.linked_giftcard.secret }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ m.linked_giftcard.secret|slice:":3" }}…
|
||||||
|
{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -22,60 +22,69 @@
|
|||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<form action="" method="post">
|
{% csrf_token %}
|
||||||
{% csrf_token %}
|
<dl class="dl-horizontal">
|
||||||
<dl class="dl-horizontal">
|
<dt>{% trans "Media type" context "reusable_media" %}</dt>
|
||||||
<dt>{% trans "Media type" context "reusable_media" %}</dt>
|
<dd>{{ medium.get_type_display }}</dd>
|
||||||
<dd>{{ medium.get_type_display }}</dd>
|
<dt>{% trans "Identifier" context "reusable_media" %}</dt>
|
||||||
<dt>{% trans "Identifier" context "reusable_media" %}</dt>
|
<dd><code>{{ medium.identifier }}</code></dd>
|
||||||
<dd><code>{{ medium.identifier }}</code></dd>
|
<dt>{% trans "Status" %}</dt>
|
||||||
<dt>{% trans "Status" %}</dt>
|
<dd>
|
||||||
<dd>
|
{% if not medium.active %}
|
||||||
{% if not medium.active %}
|
{% trans "disabled" %}
|
||||||
{% trans "disabled" %}
|
{% elif medium.is_expired %}
|
||||||
{% elif medium.is_expired %}
|
{% trans "expired" %}
|
||||||
{% trans "expired" %}
|
{% else %}
|
||||||
{% else %}
|
{% trans "active" %}
|
||||||
{% trans "active" %}
|
{% endif %}
|
||||||
{% endif %}
|
</dd>
|
||||||
</dd>
|
<dt>{% trans "Connections" context "reusable_media" %}</dt>
|
||||||
<dt>{% trans "Connections" context "reusable_media" %}</dt>
|
<dd>
|
||||||
<dd>
|
{% if medium.customer %}
|
||||||
{% if medium.customer %}
|
<span class="helper-display-block">
|
||||||
<span class="helper-display-block">
|
<span class="fa fa-user fa-fw"></span>
|
||||||
<span class="fa fa-user fa-fw"></span>
|
{% if "organizer.customers:read" in request.orgapermset %}
|
||||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=medium.customer.identifier %}">
|
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=medium.customer.identifier %}">
|
||||||
{{ medium.customer }}
|
{{ medium.customer }}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
{% else %}
|
||||||
|
{{ medium.customer }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if medium.linked_orderposition %}
|
</span>
|
||||||
<span class="helper-display-block">
|
|
||||||
<span class="fa fa-ticket fa-fw"></span>
|
|
||||||
<a href="{% url "control:event.order" event=medium.linked_orderposition.order.event.slug organizer=request.organizer.slug code=medium.linked_orderposition.order.code %}">
|
|
||||||
{{ medium.linked_orderposition.order.code }}</a>-{{ medium.linked_orderposition.positionid }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
{% if medium.linked_giftcard %}
|
|
||||||
<span class="helper-display-block">
|
|
||||||
<span class="fa fa-credit-card fa-fw"></span>
|
|
||||||
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=medium.linked_giftcard.id %}">
|
|
||||||
{{ medium.linked_giftcard.secret }}</a>
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</dd>
|
|
||||||
{% if medium.notes %}
|
|
||||||
<dt>{% trans "Notes" %}</dt>
|
|
||||||
<dd>{{ medium.notes }}</dd>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dl>
|
{% if medium.linked_orderposition %}
|
||||||
</form>
|
<span class="helper-display-block">
|
||||||
<div class="text-right">
|
<span class="fa fa-ticket fa-fw"></span>
|
||||||
<a href="{% url "control:organizer.reusable_medium.edit" organizer=request.organizer.slug pk=medium.pk %}"
|
<a href="{% url "control:event.order" event=medium.linked_orderposition.order.event.slug organizer=request.organizer.slug code=medium.linked_orderposition.order.code %}">
|
||||||
class="btn btn-default">
|
{{ medium.linked_orderposition.order.code }}</a>-{{ medium.linked_orderposition.positionid }}
|
||||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
</span>
|
||||||
</a>
|
{% endif %}
|
||||||
</div>
|
{% if medium.linked_giftcard %}
|
||||||
|
<span class="helper-display-block">
|
||||||
|
<span class="fa fa-credit-card fa-fw"></span>
|
||||||
|
{% if "organizer.giftcards:read" in request.orgapermset %}
|
||||||
|
<a href="{% url "control:organizer.giftcard" organizer=request.organizer.slug giftcard=medium.linked_giftcard.id %}">
|
||||||
|
{{ medium.linked_giftcard.secret }}
|
||||||
|
</a>
|
||||||
|
{% else %}
|
||||||
|
{{ medium.linked_giftcard.secret|slice:":3" }}…
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
|
{% if medium.notes %}
|
||||||
|
<dt>{% trans "Notes" %}</dt>
|
||||||
|
<dd>{{ medium.notes }}</dd>
|
||||||
|
{% endif %}
|
||||||
|
</dl>
|
||||||
|
{% if "organizer.reusablemedia:write" in request.orgapermset %}
|
||||||
|
<div class="text-right">
|
||||||
|
<a href="{% url "control:organizer.reusable_medium.edit" organizer=request.organizer.slug pk=medium.pk %}"
|
||||||
|
class="btn btn-default">
|
||||||
|
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<a href="{% url "control:event.subevents.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i>
|
<a href="{% url "control:event.subevents.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
{% trans "Create a new date" context "subevent" %}</a>
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i>
|
||||||
<a href="{% url "control:event.subevents.bulk" organizer=request.event.organizer.slug event=request.event.slug %}"
|
{% trans "Create a new date" context "subevent" %}</a>
|
||||||
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i>
|
<a href="{% url "control:event.subevents.bulk" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
{% trans "Create many new dates" context "subevent" %}</a>
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i>
|
||||||
|
{% trans "Create many new dates" context "subevent" %}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
@@ -84,11 +86,13 @@
|
|||||||
<table class="table table-hover table-quotas">
|
<table class="table table-hover table-quotas">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
{% if "event.subevents:write" in request.eventpermset %}
|
<th>
|
||||||
<label aria-label="{% trans "select all rows for batch-operation" %}" class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
{% endif %}
|
<label aria-label="{% trans "select all rows for batch-operation" %}" class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||||
</th>
|
{% endif %}
|
||||||
|
</th>
|
||||||
|
{% endif %}
|
||||||
<th>
|
<th>
|
||||||
{% trans "Name" %}
|
{% trans "Name" %}
|
||||||
</th>
|
</th>
|
||||||
@@ -123,11 +127,11 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for s in subevents %}
|
{% for s in subevents %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
{% if "event.subevents:write" in request.eventpermset %}
|
<td>
|
||||||
<label aria-label="{% trans "select row for batch-operation" %}" class="batch-select-label"><input type="checkbox" name="subevent" class="batch-select-checkbox" value="{{ s.pk }}"/></label>
|
<label aria-label="{% trans "select row for batch-operation" %}" class="batch-select-label"><input type="checkbox" name="subevent" class="batch-select-checkbox" value="{{ s.pk }}"/></label>
|
||||||
{% endif %}
|
</td>
|
||||||
</td>
|
{% endif %}
|
||||||
<td>
|
<td>
|
||||||
<strong><a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}">
|
<strong><a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}">
|
||||||
{{ s.name }}</a></strong><br>
|
{{ s.name }}</a></strong><br>
|
||||||
@@ -173,28 +177,32 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
<a href="{% url "control:event.orders" organizer=request.event.organizer.slug event=request.event.slug %}?subevent={{ s.id }}" class="btn btn-default btn-sm" title="{% trans "Show orders" %}"><i class="fa fa-shopping-cart" aria-hidden="true"></i></a>
|
{% if "event.orders:read" in request.eventpermset %}
|
||||||
|
<a href="{% url "control:event.orders" organizer=request.event.organizer.slug event=request.event.slug %}?subevent={{ s.id }}" class="btn btn-default btn-sm" title="{% trans "Show orders" %}"><i class="fa fa-shopping-cart" aria-hidden="true"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
{% if "event.subevents:write" in request.eventpermset %}
|
||||||
<div class="btn-group {% if forloop.revcounter0 < 2 %}dropup{% endif %}">
|
<a href="{% url "control:event.subevent" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle"
|
<div class="btn-group {% if forloop.revcounter0 < 2 %}dropup{% endif %}">
|
||||||
data-toggle="dropdown">
|
<button type="button" class="btn btn-default btn-sm dropdown-toggle"
|
||||||
<span class="fa fa-copy"></span>
|
data-toggle="dropdown">
|
||||||
</button>
|
<span class="fa fa-copy"></span>
|
||||||
<ul class="dropdown-menu dropdown-menu-right">
|
</button>
|
||||||
<li>
|
<ul class="dropdown-menu dropdown-menu-right">
|
||||||
<a href="{% url "control:event.subevents.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ s.id }}">
|
<li>
|
||||||
{% trans "Use as a template for a new date" context "subevent" %}
|
<a href="{% url "control:event.subevents.add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ s.id }}">
|
||||||
</a>
|
{% trans "Use as a template for a new date" context "subevent" %}
|
||||||
</li>
|
</a>
|
||||||
<li>
|
</li>
|
||||||
<a href="{% url "control:event.subevents.bulk" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ s.id }}">
|
<li>
|
||||||
{% trans "Use as a template for many new dates" context "subevent" %}
|
<a href="{% url "control:event.subevents.bulk" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ s.id }}">
|
||||||
</a>
|
{% trans "Use as a template for many new dates" context "subevent" %}
|
||||||
</li>
|
</a>
|
||||||
</ul>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
<a href="{% url "control:event.subevent.delete" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
</div>
|
||||||
|
<a href="{% url "control:event.subevent.delete" organizer=request.event.organizer.slug event=request.event.slug subevent=s.id %}?returnto={{ request.GET.urlencode|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -7,10 +7,12 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>
|
<h1>
|
||||||
{% trans "Waiting list" %}
|
{% trans "Waiting list" %}
|
||||||
<a href="{% url "control:event.settings" event=request.event.slug organizer=request.organizer.slug %}#waiting-list-open" class="btn btn-default">
|
{% if "event.settings.general:write" in request.eventpermset %}
|
||||||
<span class="fa fa-cog"></span>
|
<a href="{% url "control:event.settings" event=request.event.slug organizer=request.organizer.slug %}#waiting-list-open" class="btn btn-default">
|
||||||
{% trans "Settings" %}
|
<span class="fa fa-cog"></span>
|
||||||
</a>
|
{% trans "Settings" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</h1>
|
</h1>
|
||||||
{% if not request.event.settings.waiting_list_enabled %}
|
{% if not request.event.settings.waiting_list_enabled %}
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
@@ -259,31 +261,34 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right flip">
|
<td class="text-right flip">
|
||||||
{% if not e.voucher %}
|
{% if 'event.orders:write' in request.eventpermset %}
|
||||||
<button name="move_top" value="{{ e.pk }}" class="btn btn-default btn-sm"
|
{% if not e.voucher %}
|
||||||
data-toggle="tooltip" title="{% trans "Move to the top of the list" %}">
|
<button name="move_top" value="{{ e.pk }}" class="btn btn-default btn-sm"
|
||||||
<span class="fa fa-thumbs-up"></span>
|
data-toggle="tooltip" title="{% trans "Move to the top of the list" %}">
|
||||||
</button>
|
<span class="fa fa-thumbs-up"></span>
|
||||||
<button name="move_end" value="{{ e.pk }}" class="btn btn-default btn-sm"
|
</button>
|
||||||
data-toggle="tooltip" title="{% trans "Move to the end of the list" %}">
|
<button name="move_end" value="{{ e.pk }}" class="btn btn-default btn-sm"
|
||||||
<span class="fa fa-thumbs-down"></span>
|
data-toggle="tooltip" title="{% trans "Move to the end of the list" %}">
|
||||||
</button>
|
<span class="fa fa-thumbs-down"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<a href="{% url "control:event.orders.waitinglist.edit" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}"
|
<a href="{% url "control:event.orders.waitinglist.edit" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}"
|
||||||
class="btn btn-default btn-sm" title="{% trans "Edit entry" %}"
|
class="btn btn-default btn-sm" title="{% trans "Edit entry" %}"
|
||||||
data-toggle="tooltip">
|
data-toggle="tooltip">
|
||||||
<i class="fa fa-edit" aria-hidden="true"></i>
|
<i class="fa fa-edit" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
<a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}"
|
||||||
{% else %}
|
class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
<button class="btn btn-default btn-sm disabled">
|
{% else %}
|
||||||
<span class="fa fa-thumbs-up"></span>
|
<button class="btn btn-default btn-sm disabled">
|
||||||
</button>
|
<span class="fa fa-thumbs-up"></span>
|
||||||
<button class="btn btn-default btn-sm disabled">
|
</button>
|
||||||
<span class="fa fa-thumbs-down"></span>
|
<button class="btn btn-default btn-sm disabled">
|
||||||
</button>
|
<span class="fa fa-thumbs-down"></span>
|
||||||
<span class="btn btn-danger btn-sm disabled"><i class="fa fa-trash"></i></span>
|
</button>
|
||||||
|
<span class="btn btn-danger btn-sm disabled"><i class="fa fa-trash"></i></span>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi
|
|||||||
class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||||
model = CheckinList
|
model = CheckinList
|
||||||
context_object_name = 'checkinlists'
|
context_object_name = 'checkinlists'
|
||||||
permission = 'event.orders:read'
|
permission = ('event.orders:read', 'event.settings.general:write')
|
||||||
template_name = 'pretixcontrol/checkin/lists.html'
|
template_name = 'pretixcontrol/checkin/lists.html'
|
||||||
ordering = ('subevent__date_from', 'name', 'pk')
|
ordering = ('subevent__date_from', 'name', 'pk')
|
||||||
|
|
||||||
@@ -317,9 +317,9 @@ class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
cl.subevent.event = self.request.event # re-use same event object to make sure settings are cached
|
cl.subevent.event = self.request.event # re-use same event object to make sure settings are cached
|
||||||
ctx['checkinlists'] = clists
|
ctx['checkinlists'] = clists
|
||||||
|
|
||||||
ctx['can_change_organizer_settings'] = self.request.user.has_organizer_permission(
|
ctx['link_device_settings'] = self.request.user.has_organizer_permission(
|
||||||
self.request.organizer,
|
self.request.organizer,
|
||||||
'organizer.settings.general:write',
|
'organizer.devices:read',
|
||||||
self.request
|
self.request
|
||||||
)
|
)
|
||||||
ctx['filter_form'] = self.filter_form
|
ctx['filter_form'] = self.filter_form
|
||||||
@@ -578,6 +578,12 @@ class CheckInResetView(CheckInListQueryMixin, EventPermissionRequiredMixin, Asyn
|
|||||||
permission = "event.orders:write"
|
permission = "event.orders:write"
|
||||||
template_name = "pretixcontrol/checkin/reset.html"
|
template_name = "pretixcontrol/checkin/reset.html"
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
# Special case, we want two permissions to be set
|
||||||
|
if not request.user.has_event_permission(request.organizer, request.event, "event.settings.general:write", request=request):
|
||||||
|
raise PermissionDenied()
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_error_url(self, *args):
|
def get_error_url(self, *args):
|
||||||
return reverse(
|
return reverse(
|
||||||
"control:event.orders.checkinlists",
|
"control:event.orders.checkinlists",
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, Templat
|
|||||||
class PaymentProviderSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
class PaymentProviderSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
|
||||||
model = Event
|
model = Event
|
||||||
context_object_name = 'event'
|
context_object_name = 'event'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.payment:write'
|
||||||
template_name = 'pretixcontrol/event/payment_provider.html'
|
template_name = 'pretixcontrol/event/payment_provider.html'
|
||||||
|
|
||||||
def get_success_url(self) -> str:
|
def get_success_url(self) -> str:
|
||||||
@@ -618,10 +618,28 @@ class EventSettingsFormView(EventPermissionRequiredMixin, DecoupleMixin, FormVie
|
|||||||
return self.render_to_response(self.get_context_data(form=form))
|
return self.render_to_response(self.get_context_data(form=form))
|
||||||
|
|
||||||
|
|
||||||
class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView):
|
class WritePermissionMixin:
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
# Special case, we want to allow different access for read and write
|
||||||
|
if not request.user.has_event_permission(request.organizer, request.event, self.write_permission,
|
||||||
|
request=request):
|
||||||
|
raise PermissionDenied()
|
||||||
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_form(self, *args, **kwargs):
|
||||||
|
form = super().get_form(*args, **kwargs)
|
||||||
|
if not self.request.user.has_event_permission(
|
||||||
|
self.request.organizer, self.request.event, self.write_permission, request=self.request):
|
||||||
|
for f in form.fields.values():
|
||||||
|
f.disabled = True
|
||||||
|
return form
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentSettings(WritePermissionMixin, EventSettingsViewMixin, EventSettingsFormView):
|
||||||
template_name = 'pretixcontrol/event/payment.html'
|
template_name = 'pretixcontrol/event/payment.html'
|
||||||
form_class = PaymentSettingsForm
|
form_class = PaymentSettingsForm
|
||||||
permission = 'event.settings.general:write'
|
permission = ('event.settings.payment:write', 'event.settings.general:write')
|
||||||
|
write_permission = 'event.settings.payment:write'
|
||||||
|
|
||||||
def get_success_url(self) -> str:
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.settings.payment', kwargs={
|
return reverse('control:event.settings.payment', kwargs={
|
||||||
@@ -647,10 +665,11 @@ class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class TaxSettings(EventSettingsViewMixin, EventSettingsFormView):
|
class TaxSettings(WritePermissionMixin, EventSettingsViewMixin, EventSettingsFormView):
|
||||||
template_name = 'pretixcontrol/event/tax.html'
|
template_name = 'pretixcontrol/event/tax.html'
|
||||||
form_class = TaxSettingsForm
|
form_class = TaxSettingsForm
|
||||||
permission = 'event.settings.general:write'
|
permission = ('event.settings.tax:write', 'event.settings.general:write')
|
||||||
|
write_permission = 'event.settings.tax:write'
|
||||||
|
|
||||||
def get_success_url(self) -> str:
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.settings.tax', kwargs={
|
return reverse('control:event.settings.tax', kwargs={
|
||||||
@@ -666,11 +685,12 @@ class TaxSettings(EventSettingsViewMixin, EventSettingsFormView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class InvoiceSettings(EventSettingsViewMixin, EventSettingsFormView):
|
class InvoiceSettings(WritePermissionMixin, EventSettingsViewMixin, EventSettingsFormView):
|
||||||
model = Event
|
model = Event
|
||||||
form_class = InvoiceSettingsForm
|
form_class = InvoiceSettingsForm
|
||||||
template_name = 'pretixcontrol/event/invoicing.html'
|
template_name = 'pretixcontrol/event/invoicing.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = ('event.settings.invoicing:write', 'event.settings.general:write')
|
||||||
|
write_permission = 'event.settings.invoicing:write'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
types = get_transmission_types()
|
types = get_transmission_types()
|
||||||
@@ -738,7 +758,7 @@ class CancelSettings(EventSettingsViewMixin, EventSettingsFormView):
|
|||||||
|
|
||||||
|
|
||||||
class InvoicePreview(EventPermissionRequiredMixin, View):
|
class InvoicePreview(EventPermissionRequiredMixin, View):
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.invoicing:write'
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
fname, ftype, fcontent = build_preview_invoice_pdf(request.event)
|
fname, ftype, fcontent = build_preview_invoice_pdf(request.event)
|
||||||
@@ -1297,7 +1317,7 @@ class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView
|
|||||||
model = TaxRule
|
model = TaxRule
|
||||||
form_class = TaxRuleForm
|
form_class = TaxRuleForm
|
||||||
template_name = 'pretixcontrol/event/tax_edit.html'
|
template_name = 'pretixcontrol/event/tax_edit.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.tax:write'
|
||||||
context_object_name = 'taxrule'
|
context_object_name = 'taxrule'
|
||||||
|
|
||||||
def get_success_url(self) -> str:
|
def get_success_url(self) -> str:
|
||||||
@@ -1358,7 +1378,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView
|
|||||||
model = TaxRule
|
model = TaxRule
|
||||||
form_class = TaxRuleForm
|
form_class = TaxRuleForm
|
||||||
template_name = 'pretixcontrol/event/tax_edit.html'
|
template_name = 'pretixcontrol/event/tax_edit.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.tax:write'
|
||||||
context_object_name = 'rule'
|
context_object_name = 'rule'
|
||||||
|
|
||||||
def get_object(self, queryset=None) -> TaxRule:
|
def get_object(self, queryset=None) -> TaxRule:
|
||||||
@@ -1422,7 +1442,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView
|
|||||||
|
|
||||||
class TaxDefault(EventSettingsViewMixin, EventPermissionRequiredMixin, DetailView):
|
class TaxDefault(EventSettingsViewMixin, EventPermissionRequiredMixin, DetailView):
|
||||||
model = TaxRule
|
model = TaxRule
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.tax:write'
|
||||||
|
|
||||||
def get_object(self, queryset=None) -> TaxRule:
|
def get_object(self, queryset=None) -> TaxRule:
|
||||||
try:
|
try:
|
||||||
@@ -1467,7 +1487,7 @@ class TaxDefault(EventSettingsViewMixin, EventPermissionRequiredMixin, DetailVie
|
|||||||
class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, CompatDeleteView):
|
class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, CompatDeleteView):
|
||||||
model = TaxRule
|
model = TaxRule
|
||||||
template_name = 'pretixcontrol/event/tax_delete.html'
|
template_name = 'pretixcontrol/event/tax_delete.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.settings.tax:write'
|
||||||
context_object_name = 'taxrule'
|
context_object_name = 'taxrule'
|
||||||
|
|
||||||
def get_object(self, queryset=None) -> TaxRule:
|
def get_object(self, queryset=None) -> TaxRule:
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ class QuestionMixin:
|
|||||||
class QuestionView(EventPermissionRequiredMixin, ChartContainingView, DetailView):
|
class QuestionView(EventPermissionRequiredMixin, ChartContainingView, DetailView):
|
||||||
model = Question
|
model = Question
|
||||||
template_name = 'pretixcontrol/items/question.html'
|
template_name = 'pretixcontrol/items/question.html'
|
||||||
permission = 'event.items:write'
|
permission = None
|
||||||
template_name_field = 'question'
|
template_name_field = 'question'
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
|||||||
@@ -2969,7 +2969,7 @@ class RefundList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
|
|
||||||
class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView):
|
class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView):
|
||||||
template_name = 'pretixcontrol/orders/cancel.html'
|
template_name = 'pretixcontrol/orders/cancel.html'
|
||||||
permission = 'event.orders:write'
|
permission = 'event:cancel'
|
||||||
form_class = EventCancelForm
|
form_class = EventCancelForm
|
||||||
task = cancel_event
|
task = cancel_event
|
||||||
known_errortypes = ['OrderError']
|
known_errortypes = ['OrderError']
|
||||||
|
|||||||
@@ -1232,7 +1232,7 @@ class DeviceQueryMixin:
|
|||||||
class DeviceListView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
class DeviceListView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||||
model = Device
|
model = Device
|
||||||
template_name = 'pretixcontrol/organizers/devices.html'
|
template_name = 'pretixcontrol/organizers/devices.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:read'
|
||||||
context_object_name = 'devices'
|
context_object_name = 'devices'
|
||||||
paginate_by = 100
|
paginate_by = 100
|
||||||
|
|
||||||
@@ -1245,7 +1245,7 @@ class DeviceListView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermis
|
|||||||
class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
||||||
model = Device
|
model = Device
|
||||||
template_name = 'pretixcontrol/organizers/device_edit.html'
|
template_name = 'pretixcontrol/organizers/device_edit.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
form_class = DeviceForm
|
form_class = DeviceForm
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
@@ -1276,7 +1276,7 @@ class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
|||||||
|
|
||||||
class DeviceLogView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
class DeviceLogView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||||
template_name = 'pretixcontrol/organizers/device_logs.html'
|
template_name = 'pretixcontrol/organizers/device_logs.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:read'
|
||||||
model = LogEntry
|
model = LogEntry
|
||||||
context_object_name = 'logs'
|
context_object_name = 'logs'
|
||||||
paginate_by = 20
|
paginate_by = 20
|
||||||
@@ -1304,7 +1304,7 @@ class DeviceLogView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
|||||||
class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
|
class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
|
||||||
model = Device
|
model = Device
|
||||||
template_name = 'pretixcontrol/organizers/device_edit.html'
|
template_name = 'pretixcontrol/organizers/device_edit.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'device'
|
context_object_name = 'device'
|
||||||
form_class = DeviceForm
|
form_class = DeviceForm
|
||||||
|
|
||||||
@@ -1347,7 +1347,7 @@ class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
|||||||
|
|
||||||
class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView):
|
class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView):
|
||||||
template_name = 'pretixcontrol/organizers/device_bulk_edit.html'
|
template_name = 'pretixcontrol/organizers/device_bulk_edit.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'device'
|
context_object_name = 'device'
|
||||||
form_class = DeviceBulkEditForm
|
form_class = DeviceBulkEditForm
|
||||||
|
|
||||||
@@ -1461,7 +1461,7 @@ class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, Organizer
|
|||||||
class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
||||||
model = Device
|
model = Device
|
||||||
template_name = 'pretixcontrol/organizers/device_connect.html'
|
template_name = 'pretixcontrol/organizers/device_connect.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'device'
|
context_object_name = 'device'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
@@ -1493,7 +1493,7 @@ class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix
|
|||||||
class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
||||||
model = Device
|
model = Device
|
||||||
template_name = 'pretixcontrol/organizers/device_revoke.html'
|
template_name = 'pretixcontrol/organizers/device_revoke.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'device'
|
context_object_name = 'device'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
@@ -2308,7 +2308,7 @@ class RunScheduledExportView(OrganizerPermissionRequiredMixin, ExportMixin, View
|
|||||||
class GateListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
class GateListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||||
model = Gate
|
model = Gate
|
||||||
template_name = 'pretixcontrol/organizers/gates.html'
|
template_name = 'pretixcontrol/organizers/gates.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:read'
|
||||||
context_object_name = 'gates'
|
context_object_name = 'gates'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
@@ -2318,7 +2318,7 @@ class GateListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, L
|
|||||||
class GateCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
class GateCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView):
|
||||||
model = Gate
|
model = Gate
|
||||||
template_name = 'pretixcontrol/organizers/gate_edit.html'
|
template_name = 'pretixcontrol/organizers/gate_edit.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
form_class = GateForm
|
form_class = GateForm
|
||||||
|
|
||||||
def get_form_kwargs(self):
|
def get_form_kwargs(self):
|
||||||
@@ -2352,7 +2352,7 @@ class GateCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
|||||||
class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
|
class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView):
|
||||||
model = Gate
|
model = Gate
|
||||||
template_name = 'pretixcontrol/organizers/gate_edit.html'
|
template_name = 'pretixcontrol/organizers/gate_edit.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'gate'
|
context_object_name = 'gate'
|
||||||
form_class = GateForm
|
form_class = GateForm
|
||||||
|
|
||||||
@@ -2387,7 +2387,7 @@ class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
|||||||
class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView):
|
class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView):
|
||||||
model = Gate
|
model = Gate
|
||||||
template_name = 'pretixcontrol/organizers/gate_delete.html'
|
template_name = 'pretixcontrol/organizers/gate_delete.html'
|
||||||
permission = 'organizer.settings.general:write'
|
permission = 'organizer.devices:write'
|
||||||
context_object_name = 'gate'
|
context_object_name = 'gate'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
@@ -2997,7 +2997,7 @@ class SSOClientDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM
|
|||||||
class CustomerListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
class CustomerListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
||||||
model = Customer
|
model = Customer
|
||||||
template_name = 'pretixcontrol/organizers/customers.html'
|
template_name = 'pretixcontrol/organizers/customers.html'
|
||||||
permission = 'organizer.customers:write'
|
permission = 'organizer.customers:read'
|
||||||
context_object_name = 'customers'
|
context_object_name = 'customers'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
@@ -3018,7 +3018,7 @@ class CustomerListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi
|
|||||||
|
|
||||||
class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
||||||
template_name = 'pretixcontrol/organizers/customer.html'
|
template_name = 'pretixcontrol/organizers/customer.html'
|
||||||
permission = 'organizer.customers:write'
|
permission = 'organizer.customers:read'
|
||||||
context_object_name = 'orders'
|
context_object_name = 'orders'
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM
|
|||||||
model = SubEvent
|
model = SubEvent
|
||||||
context_object_name = 'subevents'
|
context_object_name = 'subevents'
|
||||||
template_name = 'pretixcontrol/subevents/index.html'
|
template_name = 'pretixcontrol/subevents/index.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = None
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset(True).prefetch_related(
|
return super().get_queryset(True).prefetch_related(
|
||||||
@@ -156,7 +156,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM
|
|||||||
class SubEventDelete(EventPermissionRequiredMixin, CompatDeleteView):
|
class SubEventDelete(EventPermissionRequiredMixin, CompatDeleteView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/delete.html'
|
template_name = 'pretixcontrol/subevents/delete.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevents'
|
context_object_name = 'subevents'
|
||||||
|
|
||||||
def get_object(self, queryset=None) -> SubEvent:
|
def get_object(self, queryset=None) -> SubEvent:
|
||||||
@@ -508,7 +508,7 @@ class SubEventEditorMixin(MetaDataEditorMixin):
|
|||||||
class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateView):
|
class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/detail.html'
|
template_name = 'pretixcontrol/subevents/detail.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
form_class = SubEventForm
|
form_class = SubEventForm
|
||||||
|
|
||||||
@@ -575,7 +575,7 @@ class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateVi
|
|||||||
class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateView):
|
class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/detail.html'
|
template_name = 'pretixcontrol/subevents/detail.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
form_class = SubEventForm
|
form_class = SubEventForm
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateVi
|
|||||||
|
|
||||||
|
|
||||||
class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View):
|
class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View):
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
@@ -740,7 +740,7 @@ class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View)
|
|||||||
class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, AsyncFormView):
|
class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, AsyncFormView):
|
||||||
model = SubEvent
|
model = SubEvent
|
||||||
template_name = 'pretixcontrol/subevents/bulk.html'
|
template_name = 'pretixcontrol/subevents/bulk.html'
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
form_class = SubEventBulkForm
|
form_class = SubEventBulkForm
|
||||||
itemformclass = BulkSubEventItemForm
|
itemformclass = BulkSubEventItemForm
|
||||||
@@ -1065,7 +1065,7 @@ class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, Asyn
|
|||||||
|
|
||||||
|
|
||||||
class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormView):
|
class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormView):
|
||||||
permission = 'event.settings.general:write'
|
permission = 'event.subevents:write'
|
||||||
form_class = SubEventBulkEditForm
|
form_class = SubEventBulkEditForm
|
||||||
template_name = 'pretixcontrol/subevents/bulk_edit.html'
|
template_name = 'pretixcontrol/subevents/bulk_edit.html'
|
||||||
context_object_name = 'subevent'
|
context_object_name = 'subevent'
|
||||||
@@ -1170,7 +1170,10 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
|||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
if self.sampled_quotas is not None:
|
if self.sampled_quotas is not None:
|
||||||
kwargs['instance'] = self.get_queryset()[0]
|
try:
|
||||||
|
kwargs['instance'] = self.get_queryset()[0]
|
||||||
|
except IndexError:
|
||||||
|
raise Http404("No matching dates")
|
||||||
|
|
||||||
formsetclass = inlineformset_factory(
|
formsetclass = inlineformset_factory(
|
||||||
SubEvent, Quota,
|
SubEvent, Quota,
|
||||||
|
|||||||
@@ -1013,10 +1013,16 @@ def item_meta_values(request, organizer, event):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@organizer_permission_required(("event.orders:read", "organizer.settings.general:write"))
|
|
||||||
# This decorator is a bit of a hack since this is not technically an organizer permission, but it does the job here --
|
|
||||||
# anyone who can see orders for any event can see the check-in log view where this is used as a filter
|
|
||||||
def devices_select2(request, **kwargs):
|
def devices_select2(request, **kwargs):
|
||||||
|
allowed = (
|
||||||
|
# This check is a bit of a hack since this is not technically an organizer permission, but it does the job here --
|
||||||
|
# anyone who can see orders for any event can see the check-in log view where this is used as a filter
|
||||||
|
request.user.has_organizer_permission(request.organizer, "organizer.devices:read", request=request) or
|
||||||
|
request.user.get_events_with_permission("event.orders:read").filter(organizer=request.organizer).exists()
|
||||||
|
)
|
||||||
|
if not allowed:
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
query = request.GET.get('query', '')
|
query = request.GET.get('query', '')
|
||||||
try:
|
try:
|
||||||
page = int(request.GET.get('page', '1'))
|
page = int(request.GET.get('page', '1'))
|
||||||
@@ -1051,10 +1057,16 @@ def devices_select2(request, **kwargs):
|
|||||||
return JsonResponse(doc)
|
return JsonResponse(doc)
|
||||||
|
|
||||||
|
|
||||||
@organizer_permission_required(("event.orders:read", "event.settings.general:write", "organizer.settings.general:write"))
|
|
||||||
# This decorator is a bit of a hack since this is not technically an organizer permission, but it does the job here --
|
|
||||||
# anyone who can see orders for any event can see the check-in log view where this is used as a filter
|
|
||||||
def gate_select2(request, **kwargs):
|
def gate_select2(request, **kwargs):
|
||||||
|
allowed = (
|
||||||
|
# This check is a bit of a hack since this is not technically an organizer permission, but it does the job here --
|
||||||
|
# anyone who can see orders for any event can see the check-in log view where this is used as a filter
|
||||||
|
request.user.has_organizer_permission(request.organizer, "organizer.devices:read", request=request) or
|
||||||
|
request.user.get_events_with_permission("event.orders:read").filter(organizer=request.organizer).exists()
|
||||||
|
)
|
||||||
|
if not allowed:
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
query = request.GET.get('query', '')
|
query = request.GET.get('query', '')
|
||||||
try:
|
try:
|
||||||
page = int(request.GET.get('page', '1'))
|
page = int(request.GET.get('page', '1'))
|
||||||
|
|||||||
@@ -28,8 +28,6 @@ OLD_TO_NEW_EVENT_MIGRATION = {
|
|||||||
"can_change_event_settings": [
|
"can_change_event_settings": [
|
||||||
"event.settings.general:write",
|
"event.settings.general:write",
|
||||||
"event.settings.payment:write",
|
"event.settings.payment:write",
|
||||||
"event.settings.plugins:write",
|
|
||||||
"event.settings.email.sender:write",
|
|
||||||
"event.settings.tax:write",
|
"event.settings.tax:write",
|
||||||
"event.settings.invoicing:write",
|
"event.settings.invoicing:write",
|
||||||
"event.subevents:write",
|
"event.subevents:write",
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ $(function () {
|
|||||||
dependents[cleanName($(this).attr("name"))] = $(this)
|
dependents[cleanName($(this).attr("name"))] = $(this)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const dependentsDisabled = [];
|
||||||
|
for (var k in dependents) {
|
||||||
|
if (dependents[k].prop("disabled")) {
|
||||||
|
dependentsDisabled.push(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!Object.values(dependents).some((el) => el.length)) {
|
if (!Object.values(dependents).some((el) => el.length)) {
|
||||||
// No address fields found, do not create request
|
// No address fields found, do not create request
|
||||||
return;
|
return;
|
||||||
@@ -101,7 +108,7 @@ $(function () {
|
|||||||
label.append('<i class="label-required">' + gettext('required') + '</i>')
|
label.append('<i class="label-required">' + gettext('required') + '</i>')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (var k in dependents) dependents[k].prop("disabled", false);
|
for (var k in dependents) dependents[k].prop("disabled", dependentsDisabled.includes(k));
|
||||||
loader.hide();
|
loader.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +165,7 @@ $(function () {
|
|||||||
required = false;
|
required = false;
|
||||||
|
|
||||||
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
|
dependent.closest(".form-group").toggle(visible).toggleClass('required', required);
|
||||||
dependent.prop("required", required).prop("disabled", false);
|
dependent.prop("required", required).prop("disabled", dependentsDisabled.includes(k));
|
||||||
}
|
}
|
||||||
}).finally(function () {
|
}).finally(function () {
|
||||||
loader.hide();
|
loader.hide();
|
||||||
|
|||||||
@@ -340,11 +340,12 @@ var form_handlers = function (el) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
el.find("input[data-checkbox-dependency]").each(function () {
|
el.find("input[data-checkbox-dependency]").each(function () {
|
||||||
|
var initially_disabled = $(this).prop("disabled");
|
||||||
var dependent = $(this),
|
var dependent = $(this),
|
||||||
dependency = findDependency($(this).attr("data-checkbox-dependency"), this),
|
dependency = findDependency($(this).attr("data-checkbox-dependency"), this),
|
||||||
update = function () {
|
update = function () {
|
||||||
var enabled = dependency.prop('checked');
|
var enabled = dependency.prop('checked');
|
||||||
dependent.prop('disabled', !enabled).closest('.form-group, .form-field-boundary').toggleClass('disabled', !enabled);
|
dependent.prop('disabled', !enabled || initially_disabled).closest('.form-group, .form-field-boundary').toggleClass('disabled', !enabled);
|
||||||
if (!enabled && !dependent.is('[data-checkbox-dependency-visual]')) {
|
if (!enabled && !dependent.is('[data-checkbox-dependency-visual]')) {
|
||||||
dependent.prop('checked', false);
|
dependent.prop('checked', false);
|
||||||
dependent.trigger('change')
|
dependent.trigger('change')
|
||||||
@@ -366,11 +367,12 @@ var form_handlers = function (el) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
el.find("div[data-display-dependency], textarea[data-display-dependency], input[data-display-dependency], select[data-display-dependency], button[data-display-dependency]").each(function () {
|
el.find("div[data-display-dependency], textarea[data-display-dependency], input[data-display-dependency], select[data-display-dependency], button[data-display-dependency]").each(function () {
|
||||||
|
var initially_disabled = $(this).prop("disabled");
|
||||||
var dependent = $(this),
|
var dependent = $(this),
|
||||||
dependency = findDependency($(this).attr("data-display-dependency"), this),
|
dependency = findDependency($(this).attr("data-display-dependency"), this),
|
||||||
update = function (ev) {
|
update = function (ev) {
|
||||||
var enabled = dependency.toArray().some(function(d) {
|
var enabled = dependency.toArray().some(function(d) {
|
||||||
if (d.disabled) return false;
|
if (d.disabled && !initially_disabled) return false;
|
||||||
if (d.type === 'checkbox' || d.type === 'radio') {
|
if (d.type === 'checkbox' || d.type === 'radio') {
|
||||||
return d.checked;
|
return d.checked;
|
||||||
} else if (d.type === 'select-one') {
|
} else if (d.type === 'select-one') {
|
||||||
@@ -391,7 +393,7 @@ var form_handlers = function (el) {
|
|||||||
}
|
}
|
||||||
var $toggling = dependent;
|
var $toggling = dependent;
|
||||||
if (dependent.is("[data-disable-dependent]")) {
|
if (dependent.is("[data-disable-dependent]")) {
|
||||||
$toggling.attr('disabled', !enabled).trigger("change");
|
$toggling.attr('disabled', !enabled || initially_disabled).trigger("change");
|
||||||
}
|
}
|
||||||
const tagName = dependent.get(0).tagName.toLowerCase()
|
const tagName = dependent.get(0).tagName.toLowerCase()
|
||||||
if (tagName !== "div" && tagName !== "button") {
|
if (tagName !== "div" && tagName !== "button") {
|
||||||
|
|||||||
@@ -1387,7 +1387,14 @@ def test_get_event_settings(token_client, organizer, event):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_patch_event_settings(token_client, organizer, event):
|
def test_patch_event_settings(token_client, organizer, event, team):
|
||||||
|
team.all_event_permissions = False
|
||||||
|
team.limit_event_permissions = {
|
||||||
|
"event.settings.general:write": True,
|
||||||
|
"event.settings.tax:write": True,
|
||||||
|
}
|
||||||
|
team.save()
|
||||||
|
|
||||||
organizer.settings.imprint_url = 'https://example.org'
|
organizer.settings.imprint_url = 'https://example.org'
|
||||||
resp = token_client.patch(
|
resp = token_client.patch(
|
||||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||||
@@ -1503,6 +1510,29 @@ def test_patch_event_settings(token_client, organizer, event):
|
|||||||
event.settings.flush()
|
event.settings.flush()
|
||||||
assert set(event.settings.locales) == set(locales)
|
assert set(event.settings.locales) == set(locales)
|
||||||
|
|
||||||
|
resp = token_client.patch(
|
||||||
|
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||||
|
{
|
||||||
|
'display_net_prices': True,
|
||||||
|
},
|
||||||
|
format='json'
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
event.settings.flush()
|
||||||
|
assert event.settings.display_net_prices
|
||||||
|
|
||||||
|
resp = token_client.patch(
|
||||||
|
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||||
|
{
|
||||||
|
'invoice_address_asked': False,
|
||||||
|
},
|
||||||
|
format='json'
|
||||||
|
)
|
||||||
|
assert resp.status_code == 400
|
||||||
|
assert resp.data == {
|
||||||
|
'invoice_address_asked': ['Setting this field requires permission event.settings.invoicing:write']
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_patch_event_settings_validation(token_client, organizer, event):
|
def test_patch_event_settings_validation(token_client, organizer, event):
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ event_urls = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
event_permission_sub_urls = [
|
event_permission_sub_urls = [
|
||||||
('get', 'event.settings.general:write', 'settings/', 200),
|
('get', None, 'settings/', 200),
|
||||||
('patch', 'event.settings.general:write', 'settings/', 200),
|
('patch', 'event.settings.general:write', 'settings/', 200),
|
||||||
('get', 'event.orders:read', 'revokedsecrets/', 200),
|
('get', 'event.orders:read', 'revokedsecrets/', 200),
|
||||||
('get', 'event.orders:read', 'revokedsecrets/1/', 404),
|
('get', 'event.orders:read', 'revokedsecrets/1/', 404),
|
||||||
@@ -118,12 +118,15 @@ event_permission_sub_urls = [
|
|||||||
('delete', 'event.items:write', 'items/1/addons/1/', 404),
|
('delete', 'event.items:write', 'items/1/addons/1/', 404),
|
||||||
('get', None, 'subevents/', 200),
|
('get', None, 'subevents/', 200),
|
||||||
('get', None, 'subevents/1/', 404),
|
('get', None, 'subevents/1/', 404),
|
||||||
|
('post', 'event.subevents:write', 'subevents/', 400),
|
||||||
|
('patch', 'event.subevents:write', 'subevents/1/', 404),
|
||||||
|
('put', 'event.subevents:write', 'subevents/1/', 404),
|
||||||
('get', None, 'taxrules/', 200),
|
('get', None, 'taxrules/', 200),
|
||||||
('get', None, 'taxrules/1/', 404),
|
('get', None, 'taxrules/1/', 404),
|
||||||
('post', 'event.settings.general:write', 'taxrules/', 400),
|
('post', 'event.settings.tax:write', 'taxrules/', 400),
|
||||||
('put', 'event.settings.general:write', 'taxrules/1/', 404),
|
('put', 'event.settings.tax:write', 'taxrules/1/', 404),
|
||||||
('patch', 'event.settings.general:write', 'taxrules/1/', 404),
|
('patch', 'event.settings.tax:write', 'taxrules/1/', 404),
|
||||||
('delete', 'event.settings.general:write', 'taxrules/1/', 404),
|
('delete', 'event.settings.tax:write', 'taxrules/1/', 404),
|
||||||
('get', 'event.settings.general:write', 'sendmail_rules/', 200),
|
('get', 'event.settings.general:write', 'sendmail_rules/', 200),
|
||||||
('get', 'event.settings.general:write', 'sendmail_rules/1/', 404),
|
('get', 'event.settings.general:write', 'sendmail_rules/1/', 404),
|
||||||
('post', 'event.settings.general:write', 'sendmail_rules/', 400),
|
('post', 'event.settings.general:write', 'sendmail_rules/', 400),
|
||||||
@@ -214,16 +217,16 @@ org_permission_sub_urls = [
|
|||||||
('put', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
('put', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
||||||
('patch', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
('patch', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
||||||
('delete', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
('delete', 'organizer.settings.general:write', 'webhooks/1/', 404),
|
||||||
('get', 'organizer.customers:write', 'customers/', 200),
|
('get', 'organizer.customers:read', 'customers/', 200),
|
||||||
('post', 'organizer.customers:write', 'customers/', 201),
|
('post', 'organizer.customers:write', 'customers/', 201),
|
||||||
('get', 'organizer.customers:write', 'customers/1/', 404),
|
('get', 'organizer.customers:read', 'customers/1/', 404),
|
||||||
('patch', 'organizer.customers:write', 'customers/1/', 404),
|
('patch', 'organizer.customers:write', 'customers/1/', 404),
|
||||||
('post', 'organizer.customers:write', 'customers/1/anonymize/', 404),
|
('post', 'organizer.customers:write', 'customers/1/anonymize/', 404),
|
||||||
('put', 'organizer.customers:write', 'customers/1/', 404),
|
('put', 'organizer.customers:write', 'customers/1/', 404),
|
||||||
('delete', 'organizer.customers:write', 'customers/1/', 404),
|
('delete', 'organizer.customers:write', 'customers/1/', 404),
|
||||||
('get', 'organizer.customers:write', 'memberships/', 200),
|
('get', 'organizer.customers:read', 'memberships/', 200),
|
||||||
('post', 'organizer.customers:write', 'memberships/', 400),
|
('post', 'organizer.customers:write', 'memberships/', 400),
|
||||||
('get', 'organizer.customers:write', 'memberships/1/', 404),
|
('get', 'organizer.customers:read', 'memberships/1/', 404),
|
||||||
('patch', 'organizer.customers:write', 'memberships/1/', 404),
|
('patch', 'organizer.customers:write', 'memberships/1/', 404),
|
||||||
('put', 'organizer.customers:write', 'memberships/1/', 404),
|
('put', 'organizer.customers:write', 'memberships/1/', 404),
|
||||||
('delete', 'organizer.customers:write', 'memberships/1/', 404),
|
('delete', 'organizer.customers:write', 'memberships/1/', 404),
|
||||||
@@ -239,18 +242,18 @@ org_permission_sub_urls = [
|
|||||||
('patch', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
('patch', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
||||||
('put', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
('put', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
||||||
('delete', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
('delete', 'organizer.settings.general:write', 'membershiptypes/1/', 404),
|
||||||
('get', 'organizer.giftcards:write', 'giftcards/', 200),
|
('get', 'organizer.giftcards:read', 'giftcards/', 200),
|
||||||
('post', 'organizer.giftcards:write', 'giftcards/', 400),
|
('post', 'organizer.giftcards:write', 'giftcards/', 400),
|
||||||
('get', 'organizer.giftcards:write', 'giftcards/1/', 404),
|
('get', 'organizer.giftcards:read', 'giftcards/1/', 404),
|
||||||
('put', 'organizer.giftcards:write', 'giftcards/1/', 404),
|
('put', 'organizer.giftcards:write', 'giftcards/1/', 404),
|
||||||
('patch', 'organizer.giftcards:write', 'giftcards/1/', 404),
|
('patch', 'organizer.giftcards:write', 'giftcards/1/', 404),
|
||||||
('get', 'organizer.giftcards:write', 'giftcards/1/transactions/', 404),
|
('get', 'organizer.giftcards:read', 'giftcards/1/transactions/', 404),
|
||||||
('get', 'organizer.giftcards:write', 'giftcards/1/transactions/1/', 404),
|
('get', 'organizer.giftcards:read', 'giftcards/1/transactions/1/', 404),
|
||||||
('get', 'organizer.settings.general:write', 'devices/', 200),
|
('get', 'organizer.devices:read', 'devices/', 200),
|
||||||
('post', 'organizer.settings.general:write', 'devices/', 400),
|
('post', 'organizer.devices:write', 'devices/', 400),
|
||||||
('get', 'organizer.settings.general:write', 'devices/1/', 404),
|
('get', 'organizer.devices:read', 'devices/1/', 404),
|
||||||
('put', 'organizer.settings.general:write', 'devices/1/', 404),
|
('put', 'organizer.devices:write', 'devices/1/', 404),
|
||||||
('patch', 'organizer.settings.general:write', 'devices/1/', 404),
|
('patch', 'organizer.devices:write', 'devices/1/', 404),
|
||||||
('get', 'organizer.teams:write', 'teams/', 200),
|
('get', 'organizer.teams:write', 'teams/', 200),
|
||||||
('post', 'organizer.teams:write', 'teams/', 400),
|
('post', 'organizer.teams:write', 'teams/', 400),
|
||||||
('get', 'organizer.teams:write', 'teams/{team_id}/', 200),
|
('get', 'organizer.teams:write', 'teams/{team_id}/', 200),
|
||||||
@@ -266,7 +269,11 @@ org_permission_sub_urls = [
|
|||||||
('get', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
|
('get', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
|
||||||
('delete', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
|
('delete', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404),
|
||||||
('post', 'organizer.teams:write', 'teams/{team_id}/tokens/', 400),
|
('post', 'organizer.teams:write', 'teams/{team_id}/tokens/', 400),
|
||||||
|
('get', 'organizer.reusablemedia:read', 'reusablemedia/', 200),
|
||||||
('get', 'organizer.reusablemedia:read', 'reusablemedia/1/', 404),
|
('get', 'organizer.reusablemedia:read', 'reusablemedia/1/', 404),
|
||||||
|
('post', 'organizer.reusablemedia:write', 'reusablemedia/', 400),
|
||||||
|
('patch', 'organizer.reusablemedia:write', 'reusablemedia/1/', 404),
|
||||||
|
('put', 'organizer.reusablemedia:write', 'reusablemedia/1/', 404),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,39 @@ def test_medium_list(token_client, organizer, event, medium):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_medium_detail(token_client, organizer, event, medium, giftcard, customer):
|
def test_medium_detail_permission_missing(token_client, organizer, event, medium, giftcard, customer, team):
|
||||||
|
team.all_organizer_permissions = False
|
||||||
|
team.limit_organizer_permissions = {
|
||||||
|
"organizer.reusablemedia:read": True,
|
||||||
|
}
|
||||||
|
team.save()
|
||||||
|
resp = token_client.get(
|
||||||
|
'/api/v1/organizers/{}/reusablemedia/{}/?expand=linked_giftcard'.format(
|
||||||
|
organizer.slug, medium.pk
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert resp.status_code == 403
|
||||||
|
assert "No permission to access gift card details." in str(resp.data)
|
||||||
|
|
||||||
|
resp = token_client.get(
|
||||||
|
'/api/v1/organizers/{}/reusablemedia/{}/?expand=customer'.format(
|
||||||
|
organizer.slug, medium.pk
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert resp.status_code == 403
|
||||||
|
assert "No permission to access customer details." in str(resp.data)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_medium_detail(token_client, organizer, event, medium, giftcard, customer, team):
|
||||||
|
team.all_organizer_permissions = False
|
||||||
|
team.limit_organizer_permissions = {
|
||||||
|
"organizer.reusablemedia:read": True,
|
||||||
|
"organizer.customers:read": True,
|
||||||
|
"organizer.giftcards:read": True,
|
||||||
|
}
|
||||||
|
team.save()
|
||||||
|
|
||||||
res = dict(TEST_MEDIUM_RES)
|
res = dict(TEST_MEDIUM_RES)
|
||||||
res["id"] = medium.pk
|
res["id"] = medium.pk
|
||||||
res["created"] = medium.created.isoformat().replace('+00:00', 'Z')
|
res["created"] = medium.created.isoformat().replace('+00:00', 'Z')
|
||||||
@@ -340,7 +372,16 @@ def test_medium_lookup_not_found(token_client, organizer, organizer2, medium):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_medium_lookup_autocreate(token_client, organizer):
|
def test_medium_lookup_autocreate(token_client, organizer, team):
|
||||||
|
team.all_organizer_permissions = False
|
||||||
|
team.limit_organizer_permissions = {
|
||||||
|
"organizer.reusablemedia:read": True,
|
||||||
|
"organizer.reusablemedia:write": True,
|
||||||
|
"organizer.customers:read": True,
|
||||||
|
"organizer.giftcards:read": True,
|
||||||
|
}
|
||||||
|
team.save()
|
||||||
|
|
||||||
# Disabled
|
# Disabled
|
||||||
resp = token_client.post(
|
resp = token_client.post(
|
||||||
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
|
'/api/v1/organizers/{}/reusablemedia/lookup/'.format(organizer.slug),
|
||||||
@@ -386,7 +427,15 @@ def test_medium_lookup_autocreate(token_client, organizer):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_medium_autocreate_giftcard(token_client, organizer):
|
def test_medium_autocreate_giftcard(token_client, organizer, team):
|
||||||
|
team.all_organizer_permissions = False
|
||||||
|
team.limit_organizer_permissions = {
|
||||||
|
"organizer.reusablemedia:write": True,
|
||||||
|
"organizer.reusablemedia:read": True,
|
||||||
|
"organizer.customers:read": True,
|
||||||
|
"organizer.giftcards:read": True,
|
||||||
|
}
|
||||||
|
team.save()
|
||||||
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard = True
|
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard = True
|
||||||
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency = 'USD'
|
organizer.settings.reusable_media_type_nfc_mf0aes_autocreate_giftcard_currency = 'USD'
|
||||||
resp = token_client.post(
|
resp = token_client.post(
|
||||||
|
|||||||
@@ -175,8 +175,6 @@ def test_team_update_legacy_add_perm(token_client, organizer, event, second_team
|
|||||||
assert second_team.limit_event_permissions == {
|
assert second_team.limit_event_permissions == {
|
||||||
"event.settings.general:write": True,
|
"event.settings.general:write": True,
|
||||||
"event.settings.payment:write": True,
|
"event.settings.payment:write": True,
|
||||||
"event.settings.plugins:write": True,
|
|
||||||
"event.settings.email.sender:write": True,
|
|
||||||
"event.settings.tax:write": True,
|
"event.settings.tax:write": True,
|
||||||
"event.settings.invoicing:write": True,
|
"event.settings.invoicing:write": True,
|
||||||
"event.subevents:write": True,
|
"event.subevents:write": True,
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ class ItemFormTest(SoupTest):
|
|||||||
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
date_from=datetime.datetime(2013, 12, 26, tzinfo=datetime.timezone.utc),
|
||||||
)
|
)
|
||||||
self.item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0, position=1)
|
self.item1 = Item.objects.create(event=self.event1, name="Standard", default_price=0, position=1)
|
||||||
t = Team.objects.create(organizer=self.orga1, all_event_permissions=True)
|
self.team = Team.objects.create(organizer=self.orga1, all_event_permissions=True)
|
||||||
t.members.add(self.user)
|
self.team.members.add(self.user)
|
||||||
t.limit_events.add(self.event1)
|
self.team.limit_events.add(self.event1)
|
||||||
self.client.login(email='dummy@dummy.dummy', password='dummy')
|
self.client.login(email='dummy@dummy.dummy', password='dummy')
|
||||||
|
|
||||||
|
|
||||||
@@ -270,6 +270,14 @@ class QuestionsTest(ItemFormTest):
|
|||||||
tbl = doc.select('.container-fluid table.table-bordered tbody')[0]
|
tbl = doc.select('.container-fluid table.table-bordered tbody')[0]
|
||||||
assert tbl.select('tr')[0].select('td')[0].text.strip() == '42'
|
assert tbl.select('tr')[0].select('td')[0].text.strip() == '42'
|
||||||
|
|
||||||
|
# Test permission requirement
|
||||||
|
self.team.all_event_permissions = False
|
||||||
|
self.team.limit_event_permissions = {}
|
||||||
|
self.team.save()
|
||||||
|
doc = self.get_doc('/control/event/%s/%s/questions/%s/' % (self.orga1.slug, self.event1.slug, c.id))
|
||||||
|
assert not doc.select('.container-fluid table.table-bordered tbody')
|
||||||
|
assert doc.select('.empty-collection')
|
||||||
|
|
||||||
def test_set_dependency(self):
|
def test_set_dependency(self):
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
|
q1 = Question.objects.create(event=self.event1, question="What country are you from?", type="C", required=True)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ from pretix.base.models import Event, Order, Organizer, Team, User
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def env():
|
def env():
|
||||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
o = Organizer.objects.create(name='Dummy', slug='dummy', plugins='pretix.plugins.banktransfer')
|
||||||
event = Event.objects.create(
|
event = Event.objects.create(
|
||||||
organizer=o, name='Dummy', slug='dummy',
|
organizer=o, name='Dummy', slug='dummy',
|
||||||
date_from=now(), plugins='pretix.plugins.banktransfer'
|
date_from=now(), plugins='pretix.plugins.banktransfer'
|
||||||
@@ -311,29 +311,29 @@ event_permission_urls = [
|
|||||||
("event.settings.general:write", "delete/", 200, HTTP_GET),
|
("event.settings.general:write", "delete/", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "dangerzone/", 200, HTTP_GET),
|
("event.settings.general:write", "dangerzone/", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/", 200, HTTP_GET),
|
("event.settings.general:write", "settings/", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/plugins", 200, HTTP_GET),
|
# ("event.settings.payment:write", "settings/payment", 200, HTTP_GET), GET allowed also with other permissions
|
||||||
("event.settings.general:write", "settings/payment", 200, HTTP_GET),
|
("event.settings.payment:write", "settings/payment", 200, HTTP_POST),
|
||||||
|
("event.settings.payment:write", "settings/payment/banktransfer", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tickets", 200, HTTP_GET),
|
("event.settings.general:write", "settings/tickets", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/email", 200, HTTP_GET),
|
("event.settings.general:write", "settings/email", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/email/setup", 200, HTTP_GET),
|
("event.settings.general:write", "settings/email/setup", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/cancel", 200, HTTP_GET),
|
("event.settings.general:write", "settings/cancel", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/invoice", 200, HTTP_GET),
|
|
||||||
("event.settings.general:write", "settings/widget", 200, HTTP_GET),
|
("event.settings.general:write", "settings/widget", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/invoice/preview", 200, HTTP_GET),
|
("event.settings.invoicing:write", "settings/invoice", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tax/", 200, HTTP_GET),
|
("event.settings.invoicing:write", "settings/invoice/preview", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tax/1/", 404, HTTP_GET),
|
("event.settings.tax:write", "settings/tax/", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tax/add", 200, HTTP_GET),
|
("event.settings.tax:write", "settings/tax/1/", 404, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tax/1/delete", 404, HTTP_GET),
|
("event.settings.tax:write", "settings/tax/add", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "settings/tax/1/default", 404, HTTP_POST),
|
("event.settings.tax:write", "settings/tax/1/delete", 404, HTTP_GET),
|
||||||
|
("event.settings.tax:write", "settings/tax/1/default", 404, HTTP_POST),
|
||||||
("event.settings.general:write", "comment/", 405, HTTP_GET),
|
("event.settings.general:write", "comment/", 405, HTTP_GET),
|
||||||
# Lists are currently not access-controlled
|
(None, "items/", 200, HTTP_GET),
|
||||||
# ("event.items:write", "items/", 200),
|
|
||||||
("event.items:write", "items/add", 200, HTTP_GET),
|
("event.items:write", "items/add", 200, HTTP_GET),
|
||||||
("event.items:write", "items/1/up", 404, HTTP_POST),
|
("event.items:write", "items/1/up", 404, HTTP_POST),
|
||||||
("event.items:write", "items/1/down", 404, HTTP_POST),
|
("event.items:write", "items/1/down", 404, HTTP_POST),
|
||||||
("event.items:write", "items/reorder/2/", 400, HTTP_POST),
|
("event.items:write", "items/reorder/2/", 400, HTTP_POST),
|
||||||
("event.items:write", "items/1/delete", 404, HTTP_GET),
|
("event.items:write", "items/1/delete", 404, HTTP_GET),
|
||||||
# ("event.items:write", "categories/", 200),
|
(None, "categories/", 200, HTTP_GET),
|
||||||
# We don't have to create categories and similar objects
|
# We don't have to create categories and similar objects
|
||||||
# for testing this, it is enough to test that a 404 error
|
# for testing this, it is enough to test that a 404 error
|
||||||
# is returned instead of a 403 one.
|
# is returned instead of a 403 one.
|
||||||
@@ -343,29 +343,30 @@ event_permission_urls = [
|
|||||||
("event.items:write", "categories/2/down", 404, HTTP_POST),
|
("event.items:write", "categories/2/down", 404, HTTP_POST),
|
||||||
("event.items:write", "categories/reorder", 400, HTTP_POST),
|
("event.items:write", "categories/reorder", 400, HTTP_POST),
|
||||||
("event.items:write", "categories/add", 200, HTTP_GET),
|
("event.items:write", "categories/add", 200, HTTP_GET),
|
||||||
# ("event.items:write", "questions/", 200, HTTP_GET),
|
(None, "questions/", 200, HTTP_GET),
|
||||||
("event.items:write", "questions/2/", 404, HTTP_GET),
|
(None, "questions/2/", 404, HTTP_GET),
|
||||||
("event.items:write", "questions/2/delete", 404, HTTP_GET),
|
("event.items:write", "questions/2/delete", 404, HTTP_GET),
|
||||||
("event.items:write", "questions/reorder", 400, HTTP_POST),
|
("event.items:write", "questions/reorder", 400, HTTP_POST),
|
||||||
("event.items:write", "questions/add", 200, HTTP_GET),
|
("event.items:write", "questions/add", 200, HTTP_GET),
|
||||||
# ("event.items:write", "quotas/", 200, HTTP_GET),
|
(None, "quotas/", 200, HTTP_GET),
|
||||||
("event.items:write", "quotas/2/change", 404, HTTP_GET),
|
("event.items:write", "quotas/2/change", 404, HTTP_GET),
|
||||||
("event.items:write", "quotas/2/delete", 404, HTTP_GET),
|
("event.items:write", "quotas/2/delete", 404, HTTP_GET),
|
||||||
("event.items:write", "quotas/add", 200, HTTP_GET),
|
("event.items:write", "quotas/add", 200, HTTP_GET),
|
||||||
# ("event.items:write", "discounts/", 200),
|
(None, "discounts/", 200, HTTP_GET),
|
||||||
# We don't have to create categories and similar objects
|
|
||||||
# for testing this, it is enough to test that a 404 error
|
|
||||||
# is returned instead of a 403 one.
|
|
||||||
("event.items:write", "discounts/2/", 404, HTTP_GET),
|
("event.items:write", "discounts/2/", 404, HTTP_GET),
|
||||||
("event.items:write", "discounts/2/delete", 404, HTTP_GET),
|
("event.items:write", "discounts/2/delete", 404, HTTP_GET),
|
||||||
("event.items:write", "discounts/2/up", 404, HTTP_POST),
|
("event.items:write", "discounts/2/up", 404, HTTP_POST),
|
||||||
("event.items:write", "discounts/2/down", 404, HTTP_POST),
|
("event.items:write", "discounts/2/down", 404, HTTP_POST),
|
||||||
("event.items:write", "discounts/reorder", 400, HTTP_POST),
|
("event.items:write", "discounts/reorder", 400, HTTP_POST),
|
||||||
("event.items:write", "discounts/add", 200, HTTP_GET),
|
("event.items:write", "discounts/add", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "subevents/", 200, HTTP_GET),
|
(None, "subevents/", 200, HTTP_GET),
|
||||||
("event.settings.general:write", "subevents/2/", 404, HTTP_GET),
|
("event.subevents:write", "subevents/2/", 404, HTTP_GET),
|
||||||
("event.settings.general:write", "subevents/2/delete", 404, HTTP_GET),
|
("event.subevents:write", "subevents/2/", 404, HTTP_POST),
|
||||||
("event.settings.general:write", "subevents/add", 200, HTTP_GET),
|
("event.subevents:write", "subevents/2/delete", 404, HTTP_GET),
|
||||||
|
("event.subevents:write", "subevents/add", 200, HTTP_GET),
|
||||||
|
("event.subevents:write", "subevents/bulk_add", 200, HTTP_GET),
|
||||||
|
("event.subevents:write", "subevents/bulk_action", 302, HTTP_POST),
|
||||||
|
("event.subevents:write", "subevents/bulk_edit", 404, HTTP_POST),
|
||||||
("event.orders:read", "orders/overview/", 200, HTTP_GET),
|
("event.orders:read", "orders/overview/", 200, HTTP_GET),
|
||||||
("event.orders:read", "orders/export/", 200, HTTP_GET),
|
("event.orders:read", "orders/export/", 200, HTTP_GET),
|
||||||
("event.orders:read", "orders/export/do", 302, HTTP_POST),
|
("event.orders:read", "orders/export/do", 302, HTTP_POST),
|
||||||
@@ -389,7 +390,7 @@ event_permission_urls = [
|
|||||||
("event.orders:write", "orders/import/", 200, HTTP_GET),
|
("event.orders:write", "orders/import/", 200, HTTP_GET),
|
||||||
("event.orders:write", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404, HTTP_GET),
|
("event.orders:write", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404, HTTP_GET),
|
||||||
("event.orders:read", "orders/FOO/answer/5/", 404, HTTP_GET),
|
("event.orders:read", "orders/FOO/answer/5/", 404, HTTP_GET),
|
||||||
("event.orders:write", "cancel/", 200, HTTP_GET),
|
("event:cancel", "cancel/", 200, HTTP_GET),
|
||||||
("event.vouchers:write", "vouchers/add", 200, HTTP_GET),
|
("event.vouchers:write", "vouchers/add", 200, HTTP_GET),
|
||||||
("event.vouchers:write", "vouchers/bulk_add", 200, HTTP_GET),
|
("event.vouchers:write", "vouchers/bulk_add", 200, HTTP_GET),
|
||||||
("event.vouchers:read", "vouchers/", 200, HTTP_GET),
|
("event.vouchers:read", "vouchers/", 200, HTTP_GET),
|
||||||
@@ -425,6 +426,8 @@ def test_wrong_event_permission(perf_patch, client, env, perm, url, code, http_m
|
|||||||
t = Team(
|
t = Team(
|
||||||
pk=2, organizer=env[2], all_events=True
|
pk=2, organizer=env[2], all_events=True
|
||||||
)
|
)
|
||||||
|
if not perm:
|
||||||
|
pytest.skip()
|
||||||
t.all_event_permissions = False
|
t.all_event_permissions = False
|
||||||
t.limit_event_permissions.pop(perm, None)
|
t.limit_event_permissions.pop(perm, None)
|
||||||
t.save()
|
t.save()
|
||||||
@@ -539,17 +542,17 @@ organizer_permission_urls = [
|
|||||||
("organizer.settings.general:write", "organizer/dummy/outgoingmails", 200),
|
("organizer.settings.general:write", "organizer/dummy/outgoingmails", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/outgoingmail/1/", 404),
|
("organizer.settings.general:write", "organizer/dummy/outgoingmail/1/", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/outgoingmail/bulk_action", 405),
|
("organizer.settings.general:write", "organizer/dummy/outgoingmail/bulk_action", 405),
|
||||||
("organizer.settings.general:write", "organizer/dummy/devices", 200),
|
("organizer.devices:read", "organizer/dummy/devices", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/devices/select2", 200),
|
("organizer.devices:read", "organizer/dummy/devices/select2", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/device/add", 200),
|
("organizer.devices:write", "organizer/dummy/device/add", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/device/1/edit", 404),
|
("organizer.devices:write", "organizer/dummy/device/1/edit", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/device/1/connect", 404),
|
("organizer.devices:write", "organizer/dummy/device/1/connect", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/device/1/revoke", 404),
|
("organizer.devices:write", "organizer/dummy/device/1/revoke", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/gates", 200),
|
("organizer.devices:read", "organizer/dummy/gates", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/gates/select2", 200),
|
("organizer.devices:read", "organizer/dummy/gates/select2", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/gate/add", 200),
|
("organizer.devices:write", "organizer/dummy/gate/add", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/gate/1/edit", 404),
|
("organizer.devices:write", "organizer/dummy/gate/1/edit", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/gate/1/delete", 404),
|
("organizer.devices:write", "organizer/dummy/gate/1/delete", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/properties", 200),
|
("organizer.settings.general:write", "organizer/dummy/properties", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/property/add", 200),
|
("organizer.settings.general:write", "organizer/dummy/property/add", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/property/1/edit", 404),
|
("organizer.settings.general:write", "organizer/dummy/property/1/edit", 404),
|
||||||
@@ -566,12 +569,12 @@ organizer_permission_urls = [
|
|||||||
("organizer.settings.general:write", "organizer/dummy/ssoprovider/add", 200),
|
("organizer.settings.general:write", "organizer/dummy/ssoprovider/add", 200),
|
||||||
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/edit", 404),
|
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/edit", 404),
|
||||||
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/delete", 404),
|
("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/delete", 404),
|
||||||
("organizer.customers:write", "organizer/dummy/customers", 200),
|
("organizer.customers:read", "organizer/dummy/customers", 200),
|
||||||
("organizer.customers:write", "organizer/dummy/customer/ABC/edit", 404),
|
("organizer.customers:write", "organizer/dummy/customer/ABC/edit", 404),
|
||||||
("organizer.customers:write", "organizer/dummy/customer/ABC/anonymize", 404),
|
("organizer.customers:write", "organizer/dummy/customer/ABC/anonymize", 404),
|
||||||
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/add", 404),
|
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/add", 404),
|
||||||
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/1/edit", 404),
|
("organizer.customers:write", "organizer/dummy/customer/ABC/membership/1/edit", 404),
|
||||||
("organizer.customers:write", "organizer/dummy/customer/ABC/", 404),
|
("organizer.customers:read", "organizer/dummy/customer/ABC/", 404),
|
||||||
("organizer.reusablemedia:read", "organizer/dummy/reusable_media", 200),
|
("organizer.reusablemedia:read", "organizer/dummy/reusable_media", 200),
|
||||||
("organizer.reusablemedia:write", "organizer/dummy/reusable_media/1/edit", 404),
|
("organizer.reusablemedia:write", "organizer/dummy/reusable_media/1/edit", 404),
|
||||||
("organizer.reusablemedia:read", "organizer/dummy/reusable_media/1/", 404),
|
("organizer.reusablemedia:read", "organizer/dummy/reusable_media/1/", 404),
|
||||||
|
|||||||
Reference in New Issue
Block a user