mirror of
https://github.com/pretix/pretix.git
synced 2025-12-05 21:32:28 +00:00
Compare commits
1 Commits
fix-pdf-bg
...
remove-rev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b07d00d90 |
@@ -554,7 +554,7 @@ class SubEventSerializer(I18nAwareModelSerializer):
|
||||
class TaxRuleSerializer(CountryFieldMixin, I18nAwareModelSerializer):
|
||||
class Meta:
|
||||
model = TaxRule
|
||||
fields = ('id', 'name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country')
|
||||
fields = ('id', 'name', 'rate', 'price_includes_tax')
|
||||
|
||||
|
||||
class EventSettingsSerializer(serializers.Serializer):
|
||||
|
||||
49
src/pretix/base/migrations/0170_auto_20201030_2109.py
Normal file
49
src/pretix/base/migrations/0170_auto_20201030_2109.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# Generated by Django 3.0.10 on 2020-10-30 21:09
|
||||
import json
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def migrate_tax_rules(apps, schema_editor):
|
||||
TaxRule = apps.get_model('pretixbase', 'TaxRule')
|
||||
for tr in TaxRule.objects.filter(eu_reverse_charge=True):
|
||||
if tr.custom_rules and tr.custom_rules != '[]':
|
||||
# Custom rules take precedence
|
||||
continue
|
||||
r = [{
|
||||
'country': str(tr.home_country),
|
||||
'address_type': '',
|
||||
'action': 'vat'
|
||||
}, {
|
||||
'country': 'EU',
|
||||
'address_type': 'business_vat_id',
|
||||
'action': 'reverse'
|
||||
}, {
|
||||
'country': 'EU',
|
||||
'address_type': '',
|
||||
'action': 'vat'
|
||||
}, {
|
||||
'country': 'ZZ',
|
||||
'address_type': '',
|
||||
'action': 'no'
|
||||
}]
|
||||
tr.custom_rules = json.dumps(r)
|
||||
tr.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('pretixbase', '0169_checkinlist_gates'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_tax_rules, migrations.RunPython.noop),
|
||||
migrations.RemoveField(
|
||||
model_name='taxrule',
|
||||
name='eu_reverse_charge',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='taxrule',
|
||||
name='home_country',
|
||||
),
|
||||
]
|
||||
@@ -1,7 +1,6 @@
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.formats import localize
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -10,7 +9,6 @@ from i18nfield.fields import I18nCharField
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models.base import LoggedModel
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.helpers.countries import FastCountryField
|
||||
|
||||
|
||||
class TaxedPrice:
|
||||
@@ -107,21 +105,6 @@ class TaxRule(LoggedModel):
|
||||
verbose_name=_("The configured product prices include the tax amount"),
|
||||
default=True,
|
||||
)
|
||||
eu_reverse_charge = models.BooleanField(
|
||||
verbose_name=_("Use EU reverse charge taxation rules"),
|
||||
default=False,
|
||||
help_text=_("Not recommended. Most events will NOT be qualified for reverse charge since the place of "
|
||||
"taxation is the location of the event. This option disables charging VAT for all customers "
|
||||
"outside the EU and for business customers in different EU countries who entered a valid EU VAT "
|
||||
"ID. Only enable this option after consulting a tax counsel. No warranty given for correct tax "
|
||||
"calculation. USE AT YOUR OWN RISK.")
|
||||
)
|
||||
home_country = FastCountryField(
|
||||
verbose_name=_('Merchant country'),
|
||||
blank=True,
|
||||
help_text=_('Your country of residence. This is the country the EU reverse charge rule will not apply in, '
|
||||
'if configured above.'),
|
||||
)
|
||||
custom_rules = models.TextField(blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
@@ -147,17 +130,13 @@ class TaxRule(LoggedModel):
|
||||
eu_reverse_charge=False
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
if self.eu_reverse_charge and not self.home_country:
|
||||
raise ValidationError(_('You need to set your home country to use the reverse charge feature.'))
|
||||
|
||||
def __str__(self):
|
||||
if self.price_includes_tax:
|
||||
s = _('incl. {rate}% {name}').format(rate=self.rate, name=self.name)
|
||||
else:
|
||||
s = _('plus {rate}% {name}').format(rate=self.rate, name=self.name)
|
||||
if self.eu_reverse_charge:
|
||||
s += ' ({})'.format(_('reverse charge enabled'))
|
||||
if self.has_custom_rules:
|
||||
s += ' ({})'.format(_('with custom rules'))
|
||||
return str(s)
|
||||
|
||||
@property
|
||||
@@ -258,50 +237,12 @@ class TaxRule(LoggedModel):
|
||||
if self._custom_rules:
|
||||
rule = self.get_matching_rule(invoice_address)
|
||||
return rule['action'] == 'reverse'
|
||||
|
||||
if not self.eu_reverse_charge:
|
||||
return False
|
||||
|
||||
if not invoice_address or not invoice_address.country:
|
||||
return False
|
||||
|
||||
if str(invoice_address.country) not in EU_COUNTRIES:
|
||||
return False
|
||||
|
||||
if invoice_address.country == self.home_country:
|
||||
return False
|
||||
|
||||
if invoice_address.is_business and invoice_address.vat_id and invoice_address.vat_id_validated:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _tax_applicable(self, invoice_address):
|
||||
if self._custom_rules:
|
||||
rule = self.get_matching_rule(invoice_address)
|
||||
return rule.get('action', 'vat') == 'vat'
|
||||
|
||||
if not self.eu_reverse_charge:
|
||||
# No reverse charge rules? Always apply VAT!
|
||||
return True
|
||||
|
||||
if not invoice_address or not invoice_address.country:
|
||||
# No country specified? Always apply VAT!
|
||||
return True
|
||||
|
||||
if str(invoice_address.country) not in EU_COUNTRIES:
|
||||
# Non-EU country? Never apply VAT!
|
||||
return False
|
||||
|
||||
if invoice_address.country == self.home_country:
|
||||
# Within same EU country? Always apply VAT!
|
||||
return True
|
||||
|
||||
if invoice_address.is_business and invoice_address.vat_id and invoice_address.vat_id_validated:
|
||||
# Reverse charge case
|
||||
return False
|
||||
|
||||
# Consumer in different EU country / invalid VAT
|
||||
return True
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
|
||||
@@ -1164,7 +1164,7 @@ TaxRuleLineFormSet = formset_factory(
|
||||
class TaxRuleForm(I18nModelForm):
|
||||
class Meta:
|
||||
model = TaxRule
|
||||
fields = ['name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country']
|
||||
fields = ['name', 'rate', 'price_includes_tax']
|
||||
|
||||
|
||||
class WidgetCodeForm(forms.Form):
|
||||
|
||||
@@ -34,15 +34,9 @@
|
||||
for more information. Note that we are not responsible for the correct handling
|
||||
of taxes in your ticket shop. If in doubt, please contact a lawyer or tax consultant.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% bootstrap_field form.eu_reverse_charge layout="control" %}
|
||||
{% bootstrap_field form.home_country layout="control" %}
|
||||
<h3>{% trans "Custom taxation rules" %}</h3>
|
||||
<div class="alert alert-warning">
|
||||
<br>
|
||||
{% blocktrans trimmed %}
|
||||
These settings are intended for professional users with very specific taxation situations.
|
||||
If you create any rule here, the reverse charge settings above will be ignored. The rules will be
|
||||
checked in order and once the first rule matches the order, it will be used and all further rules will
|
||||
The rules will be checked in order and once the first rule matches the order, it will be used and all further rules will
|
||||
be ignored. If no rule matches, tax will be charged.
|
||||
{% endblocktrans %}
|
||||
{% trans "All of these rules will only apply if an invoice address is set." %}
|
||||
|
||||
Reference in New Issue
Block a user