diff --git a/src/pretix/base/migrations/0156_cartposition_override_tax_rate.py b/src/pretix/base/migrations/0156_cartposition_override_tax_rate.py
new file mode 100644
index 0000000000..d91f159609
--- /dev/null
+++ b/src/pretix/base/migrations/0156_cartposition_override_tax_rate.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.6 on 2020-06-28 19:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pretixbase', '0155_quota_release_after_exit'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='cartposition',
+ name='override_tax_rate',
+ field=models.DecimalField(decimal_places=2, max_digits=10, null=True),
+ ),
+ ]
diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py
index c3b66adb34..b76573c4e2 100644
--- a/src/pretix/base/models/items.py
+++ b/src/pretix/base/models/items.py
@@ -448,24 +448,32 @@ class Item(LoggedModel):
return self.event.settings.show_quota_left
return self.show_quota_left
- def tax(self, price=None, base_price_is='auto', currency=None, include_bundled=False):
+ def tax(self, price=None, base_price_is='auto', currency=None, invoice_address=None, override_tax_rate=None, include_bundled=False):
price = price if price is not None else self.default_price
if not self.tax_rule:
t = TaxedPrice(gross=price, net=price, tax=Decimal('0.00'),
rate=Decimal('0.00'), name='')
else:
- t = self.tax_rule.tax(price, base_price_is=base_price_is,
- currency=currency or self.event.currency)
+ t = self.tax_rule.tax(price, base_price_is=base_price_is, invoice_address=invoice_address,
+ override_tax_rate=override_tax_rate, currency=currency or self.event.currency)
if include_bundled:
for b in self.bundles.all():
if b.designated_price and b.bundled_item.tax_rule_id != self.tax_rule_id:
if b.bundled_variation:
- bprice = b.bundled_variation.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
+ bprice = b.bundled_variation.tax(b.designated_price * b.count, base_price_is='gross',
+ invoice_address=invoice_address,
+ currency=currency)
else:
- bprice = b.bundled_item.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
- compare_price = self.tax_rule.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
+ bprice = b.bundled_item.tax(b.designated_price * b.count,
+ invoice_address=invoice_address,
+ base_price_is='gross',
+ currency=currency)
+ compare_price = self.tax_rule.tax(b.designated_price * b.count,
+ override_tax_rate=override_tax_rate,
+ invoice_address=invoice_address,
+ currency=currency)
t.net += bprice.net - compare_price.net
t.tax += bprice.tax - compare_price.tax
t.name = "MIXED!"
@@ -673,23 +681,31 @@ class ItemVariation(models.Model):
def price(self):
return self.default_price if self.default_price is not None else self.item.default_price
- def tax(self, price=None, base_price_is='auto', currency=None, include_bundled=False):
+ def tax(self, price=None, base_price_is='auto', currency=None, include_bundled=False, override_tax_rate=None,
+ invoice_address=None):
price = price if price is not None else self.price
if not self.item.tax_rule:
t = TaxedPrice(gross=price, net=price, tax=Decimal('0.00'),
rate=Decimal('0.00'), name='')
else:
- t = self.item.tax_rule.tax(price, base_price_is=base_price_is, currency=currency)
+ t = self.item.tax_rule.tax(price, base_price_is=base_price_is, currency=currency,
+ override_tax_rate=override_tax_rate,
+ invoice_address=invoice_address)
if include_bundled:
for b in self.item.bundles.all():
if b.designated_price and b.bundled_item.tax_rule_id != self.item.tax_rule_id:
if b.bundled_variation:
- bprice = b.bundled_variation.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
+ bprice = b.bundled_variation.tax(b.designated_price * b.count, base_price_is='gross',
+ currency=currency,
+ invoice_address=invoice_address)
else:
- bprice = b.bundled_item.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
- compare_price = self.item.tax_rule.tax(b.designated_price * b.count, base_price_is='gross', currency=currency)
+ bprice = b.bundled_item.tax(b.designated_price * b.count, base_price_is='gross',
+ currency=currency,
+ invoice_address=invoice_address)
+ compare_price = self.item.tax_rule.tax(b.designated_price * b.count, base_price_is='gross',
+ currency=currency, invoice_address=invoice_address)
t.net += bprice.net - compare_price.net
t.tax += bprice.tax - compare_price.tax
t.name = "MIXED!"
diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py
index ae365f396e..cba2124c15 100644
--- a/src/pretix/base/models/orders.py
+++ b/src/pretix/base/models/orders.py
@@ -1813,13 +1813,9 @@ class OrderFee(models.Model):
self.tax_rule = self.order.event.settings.tax_rate_default
if self.tax_rule:
- if self.tax_rule.tax_applicable(ia):
- tax = self.tax_rule.tax(self.value, base_price_is='gross')
- self.tax_rate = tax.rate
- self.tax_value = tax.tax
- else:
- self.tax_value = Decimal('0.00')
- self.tax_rate = Decimal('0.00')
+ tax = self.tax_rule.tax(self.value, base_price_is='gross', invoice_address=ia)
+ self.tax_rate = tax.rate
+ self.tax_value = tax.tax
else:
self.tax_value = Decimal('0.00')
self.tax_rate = Decimal('0.00')
@@ -1966,13 +1962,9 @@ class OrderPosition(AbstractPosition):
except InvoiceAddress.DoesNotExist:
ia = None
if self.tax_rule:
- if self.tax_rule.tax_applicable(ia):
- tax = self.tax_rule.tax(self.price, base_price_is='gross')
- self.tax_rate = tax.rate
- self.tax_value = tax.tax
- else:
- self.tax_value = Decimal('0.00')
- self.tax_rate = Decimal('0.00')
+ tax = self.tax_rule.tax(self.price, invoice_address=ia, base_price_is='gross')
+ self.tax_rate = tax.rate
+ self.tax_value = tax.tax
else:
self.tax_value = Decimal('0.00')
self.tax_rate = Decimal('0.00')
@@ -2111,6 +2103,10 @@ class CartPosition(AbstractPosition):
includes_tax = models.BooleanField(
default=True
)
+ override_tax_rate = models.DecimalField(
+ max_digits=10, decimal_places=2,
+ null=True, blank=True
+ )
is_bundled = models.BooleanField(default=False)
objects = ScopedManager(organizer='event__organizer')
@@ -2127,6 +2123,8 @@ class CartPosition(AbstractPosition):
@property
def tax_rate(self):
if self.includes_tax:
+ if self.override_tax_rate is not None:
+ return self.override_tax_rate
return self.item.tax(self.price, base_price_is='gross').rate
else:
return Decimal('0.00')
@@ -2134,7 +2132,7 @@ class CartPosition(AbstractPosition):
@property
def tax_value(self):
if self.includes_tax:
- return self.item.tax(self.price, base_price_is='gross').tax
+ return self.item.tax(self.price, override_tax_rate=self.override_tax_rate, base_price_is='gross').tax
else:
return Decimal('0.00')
diff --git a/src/pretix/base/models/tax.py b/src/pretix/base/models/tax.py
index bc288097e6..391af5ca26 100644
--- a/src/pretix/base/models/tax.py
+++ b/src/pretix/base/models/tax.py
@@ -164,16 +164,39 @@ class TaxRule(LoggedModel):
def has_custom_rules(self):
return self.custom_rules and self.custom_rules != '[]'
- def tax(self, base_price, base_price_is='auto', currency=None):
+ def tax_rate_for(self, invoice_address):
+ if not self._tax_applicable(invoice_address):
+ return Decimal('0.00')
+ if self.has_custom_rules:
+ rule = self.get_matching_rule(invoice_address)
+ if rule.get('action', 'vat') == 'vat' and rule.get('rate') is not None:
+ return Decimal(rule.get('rate'))
+ return Decimal(self.rate)
+
+ def tax(self, base_price, base_price_is='auto', currency=None, override_tax_rate=None, invoice_address=None,
+ subtract_from_gross=Decimal('0.00')):
from .event import Event
try:
currency = currency or self.event.currency
except Event.DoesNotExist:
pass
- if self.rate == Decimal('0.00'):
+
+ rate = Decimal(self.rate)
+ if override_tax_rate is not None:
+ rate = override_tax_rate
+ elif invoice_address:
+ adjust_rate = self.tax_rate_for(invoice_address)
+ if adjust_rate != rate:
+ normal_price = self.tax(base_price, base_price_is, currency, subtract_from_gross=subtract_from_gross)
+ base_price = normal_price.net
+ base_price_is = 'net'
+ subtract_from_gross = Decimal('0.00')
+ rate = adjust_rate
+
+ if rate == Decimal('0.00'):
return TaxedPrice(
- net=base_price, gross=base_price, tax=Decimal('0.00'),
- rate=self.rate, name=self.name
+ net=base_price - subtract_from_gross, gross=base_price - subtract_from_gross, tax=Decimal('0.00'),
+ rate=rate, name=self.name
)
if base_price_is == 'auto':
@@ -183,19 +206,22 @@ class TaxRule(LoggedModel):
base_price_is = 'net'
if base_price_is == 'gross':
- gross = base_price
- net = round_decimal(gross - (base_price * (1 - 100 / (100 + self.rate))),
+ gross = max(Decimal('0.00'), base_price - subtract_from_gross)
+ net = round_decimal(gross - (gross * (1 - 100 / (100 + rate))),
currency)
elif base_price_is == 'net':
net = base_price
- gross = round_decimal((net * (1 + self.rate / 100)),
- currency)
+ gross = round_decimal((net * (1 + rate / 100)), currency)
+ if subtract_from_gross:
+ gross -= subtract_from_gross
+ net = round_decimal(gross - (gross * (1 - 100 / (100 + rate))),
+ currency)
else:
raise ValueError('Unknown base price type: {}'.format(base_price_is))
return TaxedPrice(
net=net, gross=gross, tax=gross - net,
- rate=self.rate, name=self.name
+ rate=rate, name=self.name
)
@property
@@ -243,7 +269,7 @@ class TaxRule(LoggedModel):
return False
- def tax_applicable(self, invoice_address):
+ def _tax_applicable(self, invoice_address):
if self._custom_rules:
rule = self.get_matching_rule(invoice_address)
return rule.get('action', 'vat') == 'vat'
diff --git a/src/pretix/base/services/cart.py b/src/pretix/base/services/cart.py
index b627decd47..87bdb641c5 100644
--- a/src/pretix/base/services/cart.py
+++ b/src/pretix/base/services/cart.py
@@ -907,6 +907,7 @@ class CartManager:
price=op.price.gross, expires=self._expiry, cart_id=self.cart_id,
voucher=op.voucher, addon_to=op.addon_to if op.addon_to else None,
subevent=op.subevent, includes_tax=op.includes_tax, seat=op.seat,
+ override_tax_rate=op.price.rate,
price_before_voucher=op.price_before_voucher.gross if op.price_before_voucher is not None else None
)
if self.event.settings.attendee_names_asked:
@@ -940,7 +941,7 @@ class CartManager:
new_cart_positions.append(CartPosition(
event=self.event, item=b.item, variation=b.variation,
price=b.price.gross, expires=self._expiry, cart_id=self.cart_id,
- voucher=None, addon_to=cp,
+ voucher=None, addon_to=cp, override_tax_rate=b.price.rate,
subevent=b.subevent, includes_tax=b.includes_tax, is_bundled=True
))
@@ -1032,19 +1033,15 @@ def update_tax_rates(event: Event, cart_id: str, invoice_address: InvoiceAddress
for pos in positions:
if not pos.item.tax_rule:
continue
- charge_tax = pos.item.tax_rule.tax_applicable(invoice_address)
- if pos.includes_tax and not charge_tax:
- price = pos.item.tax(pos.price, base_price_is='gross').net
- totaldiff += price - pos.price
- pos.price = price
- pos.includes_tax = False
- pos.save(update_fields=['price', 'includes_tax'])
- elif charge_tax and not pos.includes_tax:
- price = pos.item.tax(pos.price, base_price_is='net').gross
- totaldiff += price - pos.price
- pos.price = price
- pos.includes_tax = True
- pos.save(update_fields=['price', 'includes_tax'])
+ rate = pos.item.tax_rule.tax_rate_for(invoice_address)
+
+ if pos.tax_rate != rate:
+ current_net = pos.price - pos.tax_value
+ new_gross = pos.item.tax(current_net, base_price_is='net', invoice_address=invoice_address).gross
+ pos.price = new_gross
+ pos.includes_tax = rate != Decimal('0.00')
+ pos.override_tax_rate = rate
+ pos.save(update_fields=['price', 'includes_tax', 'override_tax_rate'])
return totaldiff
@@ -1092,23 +1089,14 @@ def get_fees(event, request, total, invoice_address, provider, positions):
if payment_fee:
payment_fee_tax_rule = event.settings.tax_rate_default or TaxRule.zero()
- if payment_fee_tax_rule.tax_applicable(invoice_address):
- payment_fee_tax = payment_fee_tax_rule.tax(payment_fee, base_price_is='gross')
- fees.append(OrderFee(
- fee_type=OrderFee.FEE_TYPE_PAYMENT,
- value=payment_fee,
- tax_rate=payment_fee_tax.rate,
- tax_value=payment_fee_tax.tax,
- tax_rule=payment_fee_tax_rule
- ))
- else:
- fees.append(OrderFee(
- fee_type=OrderFee.FEE_TYPE_PAYMENT,
- value=payment_fee,
- tax_rate=Decimal('0.00'),
- tax_value=Decimal('0.00'),
- tax_rule=payment_fee_tax_rule
- ))
+ payment_fee_tax = payment_fee_tax_rule.tax(payment_fee, base_price_is='gross', invoice_address=invoice_address)
+ fees.append(OrderFee(
+ fee_type=OrderFee.FEE_TYPE_PAYMENT,
+ value=payment_fee,
+ tax_rate=payment_fee_tax.rate,
+ tax_value=payment_fee_tax.tax,
+ tax_rule=payment_fee_tax_rule
+ ))
return fees
diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py
index 38f7dfef7b..ed2f9ff4d0 100644
--- a/src/pretix/base/services/invoices.py
+++ b/src/pretix/base/services/invoices.py
@@ -24,7 +24,7 @@ from pretix.base.i18n import language
from pretix.base.models import (
Invoice, InvoiceAddress, InvoiceLine, Order, OrderFee,
)
-from pretix.base.models.tax import EU_CURRENCIES
+from pretix.base.models.tax import EU_COUNTRIES, EU_CURRENCIES
from pretix.base.services.tasks import TransactionAwareTask
from pretix.base.settings import GlobalSettingsObject
from pretix.base.signals import invoice_line_text, periodic_task
@@ -181,11 +181,17 @@ def build_invoice(invoice: Invoice) -> Invoice:
if reverse_charge:
if invoice.additional_text:
invoice.additional_text += "
"
- invoice.additional_text += pgettext(
- "invoice",
- "Reverse Charge: According to Article 194, 196 of Council Directive 2006/112/EEC, VAT liability "
- "rests with the service recipient."
- )
+ if str(invoice.invoice_to_country) in EU_COUNTRIES:
+ invoice.additional_text += pgettext(
+ "invoice",
+ "Reverse Charge: According to Article 194, 196 of Council Directive 2006/112/EEC, VAT liability "
+ "rests with the service recipient."
+ )
+ else:
+ invoice.additional_text += pgettext(
+ "invoice",
+ "VAT liability rests with the service recipient."
+ )
invoice.reverse_charge = True
invoice.save()
diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py
index 87dd0fc309..420ed754ec 100644
--- a/src/pretix/base/services/orders.py
+++ b/src/pretix/base/services/orders.py
@@ -34,7 +34,7 @@ from pretix.base.models.orders import (
generate_secret,
)
from pretix.base.models.organizer import TeamAPIToken
-from pretix.base.models.tax import TaxedPrice, TaxRule
+from pretix.base.models.tax import TaxRule
from pretix.base.payment import BasePaymentProvider, PaymentException
from pretix.base.reldate import RelativeDateWrapper
from pretix.base.services import tickets
@@ -1263,7 +1263,8 @@ class OrderChangeManager:
self._operations.append(self.RegenerateSecretOperation(position))
def change_price(self, position: OrderPosition, price: Decimal):
- price = position.item.tax(price, base_price_is='gross')
+ tax_rule = self._current_tax_rules().get(position.pk, position.tax_rule)
+ price = tax_rule.tax(price, base_price_is='gross')
if position.issued_gift_cards.exists():
raise OrderError(self.error_messages['gift_card_change'])
@@ -1279,27 +1280,38 @@ class OrderChangeManager:
self._operations.append(self.TaxRuleOperation(position_or_fee, tax_rule))
self._invoice_dirty = True
- def recalculate_taxes(self):
+ def _current_tax_rules(self):
+ tax_rules = {}
+ for p in self._operations:
+ if isinstance(p, self.TaxRuleOperation):
+ tax_rules[p.position.pk] = p.tax_rule
+ elif isinstance(p, self.ItemOperation):
+ tax_rules[p.position.pk] = p.item.tax_rule
+ return tax_rules
+
+ def recalculate_taxes(self, keep='net'):
positions = self.order.positions.select_related('item', 'item__tax_rule')
ia = self._invoice_address
+ tax_rules = self._current_tax_rules()
+
for pos in positions:
- if not pos.item.tax_rule:
+ tax_rule = tax_rules.get(pos.pk, pos.tax_rule)
+ if not tax_rule:
continue
if not pos.price:
continue
- charge_tax = pos.item.tax_rule.tax_applicable(ia)
- if pos.tax_value and not charge_tax:
- net_price = pos.price - pos.tax_value
- price = TaxedPrice(gross=net_price, net=net_price, tax=Decimal('0.00'), rate=Decimal('0.00'), name='')
- if price.gross != pos.price:
- self._totaldiff += price.gross - pos.price
- self._operations.append(self.PriceOperation(pos, price))
- elif charge_tax and not pos.tax_value:
- price = pos.item.tax(pos.price, base_price_is='net')
- if price.gross != pos.price:
- self._totaldiff += price.gross - pos.price
- self._operations.append(self.PriceOperation(pos, price))
+ new_rate = tax_rule.tax_rate_for(ia)
+ # We use override_tax_rate to make sure .tax() doesn't get clever and re-adjusts the pricing itself
+ if new_rate != pos.tax_rate:
+ if keep == 'net':
+ new_tax = tax_rule.tax(pos.price - pos.tax_value, base_price_is='net', currency=self.event.currency,
+ override_tax_rate=new_rate)
+ else:
+ new_tax = tax_rule.tax(pos.price, base_price_is='gross', currency=self.event.currency,
+ override_tax_rate=new_rate)
+ self._totaldiff += new_tax.gross - pos.price
+ self._operations.append(self.PriceOperation(pos, new_tax))
def cancel_fee(self, fee: OrderFee):
self._totaldiff -= fee.value
@@ -1345,10 +1357,7 @@ class OrderChangeManager:
if price is None:
price = get_price(item, variation, subevent=subevent, invoice_address=self._invoice_address)
else:
- if item.tax_rule and item.tax_rule.tax_applicable(self._invoice_address):
- price = item.tax(price, base_price_is='gross')
- else:
- price = TaxedPrice(gross=price, net=price, tax=Decimal('0.00'), rate=Decimal('0.00'), name='')
+ price = item.tax(price, base_price_is='gross', invoice_address=self._invoice_address)
if price is None:
raise OrderError(self.error_messages['product_invalid'])
@@ -1599,7 +1608,8 @@ class OrderChangeManager:
'new_price': op.price.gross
})
op.position.price = op.price.gross
- op.position._calculate_tax()
+ op.position.tax_rate = op.price.rate
+ op.position.tax_value = op.price.tax
op.position.save()
elif isinstance(op, self.TaxRuleOperation):
if isinstance(op.position, OrderPosition):
diff --git a/src/pretix/base/services/pricing.py b/src/pretix/base/services/pricing.py
index 71795c74d0..e95d771b6b 100644
--- a/src/pretix/base/services/pricing.py
+++ b/src/pretix/base/services/pricing.py
@@ -46,33 +46,27 @@ def get_price(item: Item, variation: ItemVariation = None,
price_includes_tax=True,
eu_reverse_charge=False,
)
- price = tax_rule.tax(price)
+
+ price = tax_rule.tax(price, invoice_address=invoice_address, subtract_from_gross=bundled_sum)
if force_custom_price and custom_price is not None and custom_price != "":
if custom_price_is_net:
- price = tax_rule.tax(custom_price, base_price_is='net')
+ price = tax_rule.tax(custom_price, base_price_is='net', invoice_address=invoice_address,
+ subtract_from_gross=bundled_sum)
else:
- price = tax_rule.tax(custom_price, base_price_is='gross')
+ price = tax_rule.tax(custom_price, base_price_is='gross', invoice_address=invoice_address,
+ subtract_from_gross=bundled_sum)
if item.free_price and custom_price is not None and custom_price != "":
if not isinstance(custom_price, Decimal):
custom_price = Decimal(str(custom_price).replace(",", "."))
if custom_price > 100000000:
raise ValueError('price_too_high')
if custom_price_is_net:
- price = tax_rule.tax(max(custom_price, price.net), base_price_is='net')
+ price = tax_rule.tax(max(custom_price, price.net), base_price_is='net',
+ invoice_address=invoice_address, subtract_from_gross=bundled_sum)
else:
- price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross')
-
- if bundled_sum:
- price = price - TaxedPrice(net=bundled_sum, gross=bundled_sum, rate=0, tax=0, name='')
- if price.gross < Decimal('0.00'):
- return TAXED_ZERO
-
- if invoice_address and not tax_rule.tax_applicable(invoice_address):
- price.tax = Decimal('0.00')
- price.rate = Decimal('0.00')
- price.gross = price.net
- price.name = ''
+ price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross',
+ invoice_address=invoice_address, subtract_from_gross=bundled_sum)
price.gross = round_decimal(price.gross, item.event.currency)
price.net = round_decimal(price.net, item.event.currency)
diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py
index ad10718e36..9c1c12f923 100644
--- a/src/pretix/control/forms/event.py
+++ b/src/pretix/control/forms/event.py
@@ -1086,6 +1086,11 @@ class TaxRuleLineForm(forms.Form):
('no', _('No VAT')),
],
)
+ rate = forms.DecimalField(
+ label=_('Deviating tax rate'),
+ max_digits=10, decimal_places=2,
+ required=False
+ )
TaxRuleLineFormSet = formset_factory(
diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py
index df539e924c..3e8281bba7 100644
--- a/src/pretix/control/forms/orders.py
+++ b/src/pretix/control/forms/orders.py
@@ -183,14 +183,15 @@ class CommentForm(I18nModelForm):
class OtherOperationsForm(forms.Form):
- recalculate_taxes = forms.BooleanField(
+ recalculate_taxes = forms.ChoiceField(
label=_('Re-calculate taxes'),
required=False,
- help_text=_(
- 'This operation re-checks if taxes should be paid to the items due to e.g. configured reverse charge rules '
- 'and changes the prices and tax values accordingly. This is useful e.g. after an invoice address change. '
- 'Use with care and only if you need to. Note that rounding differences might occur in this procedure.'
- )
+ choices=(
+ ('', _('Do not re-calculate taxes')),
+ ('gross', _('Re-calculate taxes based on address and product settings, keep gross amount the same.')),
+ ('net', _('Re-calculate taxes based on address and product settings, keep net amount the same.')),
+ ),
+ widget=forms.RadioSelect
)
reissue_invoice = forms.BooleanField(
label=_('Issue a new invoice if required'),
diff --git a/src/pretix/control/templates/pretixcontrol/event/tax_edit.html b/src/pretix/control/templates/pretixcontrol/event/tax_edit.html
index 896f7b6dcc..2d06661fcc 100644
--- a/src/pretix/control/templates/pretixcontrol/event/tax_edit.html
+++ b/src/pretix/control/templates/pretixcontrol/event/tax_edit.html
@@ -59,7 +59,7 @@
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
-