mirror of
https://github.com/pretix/pretix.git
synced 2026-08-25 13:12:00 +00:00
Add settings page
This commit is contained in:
@@ -78,9 +78,9 @@ from pretix.control.forms import (
|
|||||||
from pretix.helpers.countries import CachedCountries
|
from pretix.helpers.countries import CachedCountries
|
||||||
|
|
||||||
ROUNDING_MODES = (
|
ROUNDING_MODES = (
|
||||||
('line', _('Rounding every line individually')),
|
('line', _('Round taxes for every line individually')),
|
||||||
('sum_by_net', _('Rounding by order total, keeping net prices stable')),
|
('sum_by_net', _('Round taxes by order total, keeping net prices stable')),
|
||||||
('sum_by_gross', _('Rounding by order total, keeping gross prices stable')),
|
('sum_by_gross', _('Round taxes by order total, keeping gross prices stable')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ DEFAULTS = {
|
|||||||
'form_class': forms.BooleanField,
|
'form_class': forms.BooleanField,
|
||||||
'serializer_class': serializers.BooleanField,
|
'serializer_class': serializers.BooleanField,
|
||||||
'form_kwargs': dict(
|
'form_kwargs': dict(
|
||||||
label=_("Show net prices instead of gross prices in the product list (not recommended!)"),
|
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 "
|
||||||
"paid."),
|
"paid."),
|
||||||
|
|
||||||
@@ -480,6 +480,11 @@ DEFAULTS = {
|
|||||||
label=_("Rounding of taxes"),
|
label=_("Rounding of taxes"),
|
||||||
widget=forms.RadioSelect,
|
widget=forms.RadioSelect,
|
||||||
choices=ROUNDING_MODES,
|
choices=ROUNDING_MODES,
|
||||||
|
help_text=_(
|
||||||
|
"Note that if you transfer your sales data from pretix to an external system for tax reporting, you "
|
||||||
|
"need to make sure to account for possible rounding differences if your external system rounds "
|
||||||
|
"differently than pretix."
|
||||||
|
)
|
||||||
),
|
),
|
||||||
'serializer_kwargs': dict(
|
'serializer_kwargs': dict(
|
||||||
choices=ROUNDING_MODES,
|
choices=ROUNDING_MODES,
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
|
|||||||
from pretix.base.services.placeholders import FormPlaceholderMixin
|
from pretix.base.services.placeholders import FormPlaceholderMixin
|
||||||
from pretix.base.settings import (
|
from pretix.base.settings import (
|
||||||
COUNTRIES_WITH_STATE_IN_ADDRESS, DEFAULTS, PERSON_NAME_SCHEMES,
|
COUNTRIES_WITH_STATE_IN_ADDRESS, DEFAULTS, PERSON_NAME_SCHEMES,
|
||||||
PERSON_NAME_TITLE_GROUPS, validate_event_settings,
|
PERSON_NAME_TITLE_GROUPS, ROUNDING_MODES, validate_event_settings,
|
||||||
)
|
)
|
||||||
from pretix.base.validators import multimail_validate
|
from pretix.base.validators import multimail_validate
|
||||||
from pretix.control.forms import (
|
from pretix.control.forms import (
|
||||||
@@ -541,7 +541,6 @@ class EventSettingsForm(EventSettingsValidationMixin, FormPlaceholderMixin, Sett
|
|||||||
'show_date_to',
|
'show_date_to',
|
||||||
'show_times',
|
'show_times',
|
||||||
'show_items_outside_presale_period',
|
'show_items_outside_presale_period',
|
||||||
'display_net_prices',
|
|
||||||
'hide_prices_from_attendees',
|
'hide_prices_from_attendees',
|
||||||
'presale_start_show_date',
|
'presale_start_show_date',
|
||||||
'locales',
|
'locales',
|
||||||
@@ -799,6 +798,76 @@ class PaymentSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class DisplayNetPricesBooleanSelect(forms.RadioSelect):
|
||||||
|
def __init__(self, attrs=None):
|
||||||
|
choices = (
|
||||||
|
("false", format_html(
|
||||||
|
'{} <br><span class="text-muted">{}</span>',
|
||||||
|
_("Prices including tax"),
|
||||||
|
_("Recommended if you sell tickets at least partly to consumers.")
|
||||||
|
)),
|
||||||
|
("true", format_html(
|
||||||
|
'{} <br><span class="text-muted">{}</span>',
|
||||||
|
_("Prices excluding tax"),
|
||||||
|
_("Recommended only if you sell tickets primarily to business customers.")
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
super().__init__(attrs, choices)
|
||||||
|
|
||||||
|
def format_value(self, value):
|
||||||
|
try:
|
||||||
|
return {
|
||||||
|
True: "true",
|
||||||
|
False: "false",
|
||||||
|
"true": "true",
|
||||||
|
"false": "false",
|
||||||
|
}[value]
|
||||||
|
except KeyError:
|
||||||
|
return "unknown"
|
||||||
|
|
||||||
|
def value_from_datadict(self, data, files, name):
|
||||||
|
value = data.get(name)
|
||||||
|
return {
|
||||||
|
True: True,
|
||||||
|
"True": True,
|
||||||
|
"False": False,
|
||||||
|
False: False,
|
||||||
|
"true": True,
|
||||||
|
"false": False,
|
||||||
|
}.get(value)
|
||||||
|
|
||||||
|
|
||||||
|
class TaxSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
||||||
|
auto_fields = [
|
||||||
|
'display_net_prices',
|
||||||
|
'tax_rounding',
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.fields["display_net_prices"].label = _("Prices shown to customer")
|
||||||
|
self.fields["display_net_prices"].widget = DisplayNetPricesBooleanSelect()
|
||||||
|
help_text = {
|
||||||
|
"line": _("Recommended when e-invoicing is not required. Each product will be sold with the advertised "
|
||||||
|
"net and gross price. However, in orders of more than one product, the total tax amount "
|
||||||
|
"can differ from when it would be computed from the order total."),
|
||||||
|
"sum_by_net": _("Recommended for e-invoicing in Europe when you primarily sell to business customers and "
|
||||||
|
"show prices to customers excluding tax. "
|
||||||
|
"For orders of more than one product, the gross price of some products may be changed "
|
||||||
|
"automatically to ensure correct rounding of the order total, while the net prices "
|
||||||
|
"stay as configured. This may cause the actual payment amount to differ from buying the "
|
||||||
|
"products individually."),
|
||||||
|
"sum_by_gross": _("Recommended for e-invoicing in Europe when you primarily sell to consumers. "
|
||||||
|
"For an order of more than one product, the net price of some products may be changed "
|
||||||
|
"automatically to ensure correct rounding of the order total, while the gross prices "
|
||||||
|
"stay as configured."),
|
||||||
|
}
|
||||||
|
self.fields["tax_rounding"].choices = (
|
||||||
|
(k, format_html('{}<br><span class="text-muted">{}</span>', v, help_text.get(k, "")))
|
||||||
|
for k, v in ROUNDING_MODES
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ProviderForm(SettingsForm):
|
class ProviderForm(SettingsForm):
|
||||||
"""
|
"""
|
||||||
This is a SettingsForm, but if fields are set to required=True, validation
|
This is a SettingsForm, but if fields are set to required=True, validation
|
||||||
@@ -881,7 +950,6 @@ class InvoiceSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
|||||||
'invoice_logo_image',
|
'invoice_logo_image',
|
||||||
'invoice_renderer_highlight_order_code',
|
'invoice_renderer_highlight_order_code',
|
||||||
'invoice_renderer_font',
|
'invoice_renderer_font',
|
||||||
'tax_rounding',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
invoice_generate_sales_channels = forms.MultipleChoiceField(
|
invoice_generate_sales_channels = forms.MultipleChoiceField(
|
||||||
@@ -1511,7 +1579,10 @@ class TaxRuleLineForm(I18nForm):
|
|||||||
rate = forms.DecimalField(
|
rate = forms.DecimalField(
|
||||||
label=_('Deviating tax rate'),
|
label=_('Deviating tax rate'),
|
||||||
max_digits=10, decimal_places=2,
|
max_digits=10, decimal_places=2,
|
||||||
required=False
|
required=False,
|
||||||
|
widget=forms.NumberInput(attrs={
|
||||||
|
'placeholder': _('Deviating tax rate'),
|
||||||
|
})
|
||||||
)
|
)
|
||||||
invoice_text = I18nFormField(
|
invoice_text = I18nFormField(
|
||||||
label=_('Text on invoice'),
|
label=_('Text on invoice'),
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ def get_event_navigation(request: HttpRequest):
|
|||||||
'active': url.url_name == 'event.settings.mail',
|
'active': url.url_name == 'event.settings.mail',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Tax rules'),
|
'label': _('Taxes'),
|
||||||
'url': reverse('control:event.settings.tax', kwargs={
|
'url': reverse('control:event.settings.tax', kwargs={
|
||||||
'event': request.event.slug,
|
'event': request.event.slug,
|
||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
{% bootstrap_field form.invoice_numbers_prefix layout="control" %}
|
{% bootstrap_field form.invoice_numbers_prefix layout="control" %}
|
||||||
{% bootstrap_field form.invoice_numbers_prefix_cancellations layout="control" %}
|
{% bootstrap_field form.invoice_numbers_prefix_cancellations layout="control" %}
|
||||||
{% bootstrap_field form.invoice_numbers_counter_length layout="control" %}
|
{% bootstrap_field form.invoice_numbers_counter_length layout="control" %}
|
||||||
{% bootstrap_field form.tax_rounding layout="control" %}
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{% trans "Address form" %}</legend>
|
<legend>{% trans "Address form" %}</legend>
|
||||||
|
|||||||
@@ -243,7 +243,6 @@
|
|||||||
{% bootstrap_field sform.show_times layout="control" %}
|
{% bootstrap_field sform.show_times layout="control" %}
|
||||||
<h4>{% trans "Product list" %}</h4>
|
<h4>{% trans "Product list" %}</h4>
|
||||||
{% bootstrap_field sform.show_quota_left layout="control" %}
|
{% bootstrap_field sform.show_quota_left layout="control" %}
|
||||||
{% bootstrap_field sform.display_net_prices layout="control" %}
|
|
||||||
{% bootstrap_field sform.show_variations_expanded layout="control" %}
|
{% bootstrap_field sform.show_variations_expanded layout="control" %}
|
||||||
{% bootstrap_field sform.hide_sold_out layout="control" %}
|
{% bootstrap_field sform.hide_sold_out layout="control" %}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
{% extends "pretixcontrol/event/settings_base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% block title %}{% trans "Taxes" %}{% endblock %}
|
||||||
|
{% block inside %}
|
||||||
|
<h1>{% trans "Taxes" %}</h1>
|
||||||
|
{% bootstrap_form_errors form layout="control" %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Tax rules" %}</legend>
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
Tax rules define different taxation scenarios that can then be assigned to the individual products.
|
||||||
|
Each tax rule contains a default tax rate and can optionally contain additional rules that depend
|
||||||
|
on the customer's country and type.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if taxrules|length == 0 %}
|
||||||
|
<div class="empty-collection">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
You haven't created any tax rules yet.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-quotas">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Name" %}</th>
|
||||||
|
<th>{% trans "Default" %}</th>
|
||||||
|
<th>{% trans "Usage" %}</th>
|
||||||
|
<th>{% trans "Rate" %}</th>
|
||||||
|
<th class="action-col-2"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for tr in taxrules %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong><a
|
||||||
|
href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
||||||
|
{{ tr.internal_name|default:tr.name }}
|
||||||
|
</a></strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if tr.default %}
|
||||||
|
<span class="text-success">
|
||||||
|
<span class="fa fa-check"></span>
|
||||||
|
{% trans "Default" %}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<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 %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-default btn-sm">
|
||||||
|
{% trans "Make default" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% blocktrans trimmed count count=tr.c_items %}
|
||||||
|
{{ count }} product
|
||||||
|
{% plural %}
|
||||||
|
{{ count }} products
|
||||||
|
{% endblocktrans %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if tr.price_includes_tax %}
|
||||||
|
{% blocktrans with rate=tr.rate %}incl. {{ rate }} %{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktrans with rate=tr.rate %}excl. {{ rate }} %{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tr.has_custom_rules %}
|
||||||
|
<br><small>{% trans "with custom rules" %}</small>
|
||||||
|
{% elif tr.eu_reverse_charge %}
|
||||||
|
<br><small>{% trans "reverse charge enabled" %}</small>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<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 %}"
|
||||||
|
class="btn btn-default btn-sm"><i class="fa fa-edit"></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>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">
|
||||||
|
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||||
|
class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</fieldset>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Tax settings" %}</legend>
|
||||||
|
{% bootstrap_field form.tax_rounding layout="control" %}
|
||||||
|
{% bootstrap_field form.display_net_prices layout="control" %}
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group submit-group">
|
||||||
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
|
{% trans "Save" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
{% extends "pretixcontrol/event/settings_base.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% block title %}{% trans "Tax rules" %}{% endblock %}
|
|
||||||
{% block inside %}
|
|
||||||
<h1>{% trans "Tax rules" %}</h1>
|
|
||||||
{% if taxrules|length == 0 %}
|
|
||||||
<div class="empty-collection">
|
|
||||||
<p>
|
|
||||||
{% blocktrans trimmed %}
|
|
||||||
You haven't created any tax rules yet.
|
|
||||||
{% endblocktrans %}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<p>
|
|
||||||
<a href="{% url "control:event.settings.tax.add" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default"><i class="fa fa-plus"></i> {% trans "Create a new tax rule" %}
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-hover table-quotas">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Name" %}</th>
|
|
||||||
<th>{% trans "Default" %}</th>
|
|
||||||
<th>{% trans "Rate" %}</th>
|
|
||||||
<th class="action-col-2"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for tr in taxrules %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<strong><a href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
|
|
||||||
{{ tr.internal_name|default:tr.name }}
|
|
||||||
</a></strong>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if tr.default %}
|
|
||||||
<span class="text-success">
|
|
||||||
<span class="fa fa-check"></span>
|
|
||||||
{% trans "Default" %}
|
|
||||||
</span>
|
|
||||||
{% else %}
|
|
||||||
<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 %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<button class="btn btn-default btn-sm">
|
|
||||||
{% trans "Make default" %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if tr.price_includes_tax %}
|
|
||||||
{% blocktrans with rate=tr.rate%}incl. {{ rate }} %{% endblocktrans %}
|
|
||||||
{% else %}
|
|
||||||
{% blocktrans with rate=tr.rate%}excl. {{ rate }} %{% endblocktrans %}
|
|
||||||
{% endif %}
|
|
||||||
{% if tr.eu_reverse_charge %}
|
|
||||||
({% trans "reverse charge enabled" %})
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<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 %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></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>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% include "pretixcontrol/pagination.html" %}
|
|
||||||
{% endblock %}
|
|
||||||
@@ -286,7 +286,7 @@ urlpatterns = [
|
|||||||
re_path(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'),
|
re_path(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'),
|
||||||
re_path(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'),
|
re_path(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'),
|
||||||
re_path(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'),
|
re_path(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'),
|
||||||
re_path(r'^settings/tax/$', event.TaxList.as_view(), name='event.settings.tax'),
|
re_path(r'^settings/tax/$', event.TaxSettings.as_view(), name='event.settings.tax'),
|
||||||
re_path(r'^settings/tax/(?P<rule>\d+)/$', event.TaxUpdate.as_view(), name='event.settings.tax.edit'),
|
re_path(r'^settings/tax/(?P<rule>\d+)/$', event.TaxUpdate.as_view(), name='event.settings.tax.edit'),
|
||||||
re_path(r'^settings/tax/add$', event.TaxCreate.as_view(), name='event.settings.tax.add'),
|
re_path(r'^settings/tax/add$', event.TaxCreate.as_view(), name='event.settings.tax.add'),
|
||||||
re_path(r'^settings/tax/(?P<rule>\d+)/delete$', event.TaxDelete.as_view(), name='event.settings.tax.delete'),
|
re_path(r'^settings/tax/(?P<rule>\d+)/delete$', event.TaxDelete.as_view(), name='event.settings.tax.delete'),
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import ProtectedError
|
from django.db.models import Count, ProtectedError
|
||||||
from django.forms import inlineformset_factory
|
from django.forms import inlineformset_factory
|
||||||
from django.http import (
|
from django.http import (
|
||||||
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed,
|
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed,
|
||||||
@@ -87,7 +87,7 @@ from pretix.control.forms.event import (
|
|||||||
EventFooterLinkFormset, EventMetaValueForm, EventSettingsForm,
|
EventFooterLinkFormset, EventMetaValueForm, EventSettingsForm,
|
||||||
EventUpdateForm, InvoiceSettingsForm, ItemMetaPropertyForm,
|
EventUpdateForm, InvoiceSettingsForm, ItemMetaPropertyForm,
|
||||||
MailSettingsForm, PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
MailSettingsForm, PaymentSettingsForm, ProviderForm, QuickSetupForm,
|
||||||
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
|
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet, TaxSettingsForm,
|
||||||
TicketSettingsForm, WidgetCodeForm,
|
TicketSettingsForm, WidgetCodeForm,
|
||||||
)
|
)
|
||||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||||
@@ -620,6 +620,25 @@ class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class TaxSettings(EventSettingsViewMixin, EventSettingsFormView):
|
||||||
|
template_name = 'pretixcontrol/event/tax.html'
|
||||||
|
form_class = TaxSettingsForm
|
||||||
|
permission = 'can_change_event_settings'
|
||||||
|
|
||||||
|
def get_success_url(self) -> str:
|
||||||
|
return reverse('control:event.settings.tax', kwargs={
|
||||||
|
'organizer': self.request.organizer.slug,
|
||||||
|
'event': self.request.event.slug,
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
|
context = super().get_context_data(*args, **kwargs)
|
||||||
|
context['taxrules'] = self.request.event.tax_rules.annotate(
|
||||||
|
c_items=Count("item")
|
||||||
|
).all()
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class InvoiceSettings(EventSettingsViewMixin, EventSettingsFormView):
|
class InvoiceSettings(EventSettingsViewMixin, EventSettingsFormView):
|
||||||
model = Event
|
model = Event
|
||||||
form_class = InvoiceSettingsForm
|
form_class = InvoiceSettingsForm
|
||||||
@@ -1219,16 +1238,6 @@ class EventComment(EventPermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class TaxList(EventSettingsViewMixin, EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|
||||||
model = TaxRule
|
|
||||||
context_object_name = 'taxrules'
|
|
||||||
template_name = 'pretixcontrol/event/tax_index.html'
|
|
||||||
permission = 'can_change_event_settings'
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return self.request.event.tax_rules.all()
|
|
||||||
|
|
||||||
|
|
||||||
class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView):
|
class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView):
|
||||||
model = TaxRule
|
model = TaxRule
|
||||||
form_class = TaxRuleForm
|
form_class = TaxRuleForm
|
||||||
|
|||||||
Reference in New Issue
Block a user