diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index a67cb2a268..742174681f 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -737,7 +737,8 @@ class InvoiceAddress(models.Model): city = models.CharField(max_length=255, verbose_name=_('City'), blank=False) country_old = models.CharField(max_length=255, verbose_name=_('Country'), blank=False) country = CountryField(verbose_name=_('Country'), blank=False, blank_label=_('Select country')) - vat_id = models.CharField(max_length=255, blank=True, verbose_name=_('VAT ID')) + vat_id = models.CharField(max_length=255, blank=True, verbose_name=_('VAT ID'), + help_text=_('Only for business customers within the EU.')) def cachedticket_name(instance, filename: str) -> str: diff --git a/src/pretix/presale/forms/checkout.py b/src/pretix/presale/forms/checkout.py index d355f3bfff..bc6e038218 100644 --- a/src/pretix/presale/forms/checkout.py +++ b/src/pretix/presale/forms/checkout.py @@ -48,22 +48,54 @@ class ContactForm(forms.Form): raise ValidationError(_('Please enter the same email address twice.')) +class BusinessBooleanRadio(forms.RadioSelect): + def __init__(self, attrs=None): + choices = ( + ('individual', _('Individual customer')), + ('business', _('Business customer')), + ) + super().__init__(attrs, choices) + + def format_value(self, value): + try: + return {True: 'business', False: 'individual'}[value] + except KeyError: + return 'individual' + + def value_from_datadict(self, data, files, name): + value = data.get(name) + return { + 'business': True, + True: True, + 'True': True, + 'individual': False, + 'False': False, + False: False, + }.get(value) + + class InvoiceAddressForm(forms.ModelForm): required_css_class = 'required' class Meta: model = InvoiceAddress - fields = ('company', 'name', 'street', 'zipcode', 'city', 'country', 'vat_id') + fields = ('is_business', 'company', 'name', 'street', 'zipcode', 'city', 'country', 'vat_id') widgets = { + 'is_business': BusinessBooleanRadio, 'street': forms.Textarea(attrs={'rows': 2, 'placeholder': _('Street and Number')}), - 'company': forms.TextInput(attrs={'data-typocheck-source': '1'}), - 'name': forms.TextInput(attrs={'data-typocheck-source': '1'}), + 'company': forms.TextInput(attrs={'data-typocheck-source': '1', + 'data-display-dependency': '#id_is_business_1', + 'data-required-if': '#id_is_business_1'}), + 'name': forms.TextInput(attrs={'data-typocheck-source': '1', 'data-required-if': '#id_is_business_0'}), + 'vat_id': forms.TextInput(attrs={'data-display-dependency': '#id_is_business_1'}), + } + labels = { + 'is_business': '' } def __init__(self, *args, **kwargs): self.event = event = kwargs.pop('event') super().__init__(*args, **kwargs) - self.fields['name'].form_group_class = 'required' if not event.settings.invoice_address_vatid: del self.fields['vat_id'] if not event.settings.invoice_address_required: diff --git a/src/pretix/static/pretixpresale/js/ui/main.js b/src/pretix/static/pretixpresale/js/ui/main.js index 92041fd92e..ecd2246530 100644 --- a/src/pretix/static/pretixpresale/js/ui/main.js +++ b/src/pretix/static/pretixpresale/js/ui/main.js @@ -90,6 +90,35 @@ $(function () { $tr.show(); }); + // Invoice address form + $("input[data-required-if]").each(function () { + var dependent = $(this), + dependency = $($(this).attr("data-required-if")), + update = function (ev) { + var enabled = (dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val(); + dependent.prop('required', enabled).closest('.form-group').toggleClass('required', enabled); + }; + update(); + dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("change", update); + dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("dp.change", update); + }); + + $("input[data-display-dependency]").each(function () { + var dependent = $(this), + dependency = $($(this).attr("data-display-dependency")), + update = function (ev) { + var enabled = (dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val(); + if (ev) { + dependent.closest('.form-group').slideToggle(enabled); + } else { + dependent.closest('.form-group').toggle(enabled); + } + }; + update(); + dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("change", update); + dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("dp.change", update); + }); + // Lightbox lightbox.init(); });