forked from CGM_Public/pretix_original
Add new signal checkout_all_optional
This commit is contained in:
@@ -26,7 +26,7 @@ Frontend
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, fee_calculation_for_cart, contact_form_fields, question_form_fields, checkout_confirm_messages, checkout_confirm_page_content
|
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, fee_calculation_for_cart, contact_form_fields, question_form_fields, checkout_confirm_messages, checkout_confirm_page_content, checkout_all_optional
|
||||||
|
|
||||||
|
|
||||||
.. automodule:: pretix.presale.signals
|
.. automodule:: pretix.presale.signals
|
||||||
|
|||||||
@@ -291,17 +291,18 @@ class BaseInvoiceAddressForm(forms.ModelForm):
|
|||||||
self.event = event = kwargs.pop('event')
|
self.event = event = kwargs.pop('event')
|
||||||
self.request = kwargs.pop('request', None)
|
self.request = kwargs.pop('request', None)
|
||||||
self.validate_vat_id = kwargs.pop('validate_vat_id')
|
self.validate_vat_id = kwargs.pop('validate_vat_id')
|
||||||
|
self.all_optional = kwargs.pop('all_optional', False)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
if not event.settings.invoice_address_vatid:
|
if not event.settings.invoice_address_vatid:
|
||||||
del self.fields['vat_id']
|
del self.fields['vat_id']
|
||||||
|
|
||||||
if not event.settings.invoice_address_required:
|
if not event.settings.invoice_address_required or self.all_optional:
|
||||||
for k, f in self.fields.items():
|
for k, f in self.fields.items():
|
||||||
f.required = False
|
f.required = False
|
||||||
f.widget.is_required = False
|
f.widget.is_required = False
|
||||||
if 'required' in f.widget.attrs:
|
if 'required' in f.widget.attrs:
|
||||||
del f.widget.attrs['required']
|
del f.widget.attrs['required']
|
||||||
elif event.settings.invoice_address_company_required:
|
elif event.settings.invoice_address_company_required and not self.all_optional:
|
||||||
self.initial['is_business'] = True
|
self.initial['is_business'] = True
|
||||||
|
|
||||||
self.fields['is_business'].widget = BusinessBooleanRadio(require_business=True)
|
self.fields['is_business'].widget = BusinessBooleanRadio(require_business=True)
|
||||||
@@ -314,12 +315,12 @@ class BaseInvoiceAddressForm(forms.ModelForm):
|
|||||||
|
|
||||||
self.fields['name_parts'] = NamePartsFormField(
|
self.fields['name_parts'] = NamePartsFormField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
required=event.settings.invoice_name_required,
|
required=event.settings.invoice_name_required and not self.all_optional,
|
||||||
scheme=event.settings.name_scheme,
|
scheme=event.settings.name_scheme,
|
||||||
label=_('Name'),
|
label=_('Name'),
|
||||||
initial=(self.instance.name_parts if self.instance else self.instance.name_parts),
|
initial=(self.instance.name_parts if self.instance else self.instance.name_parts),
|
||||||
)
|
)
|
||||||
if event.settings.invoice_address_required and not event.settings.invoice_address_company_required:
|
if event.settings.invoice_address_required and not event.settings.invoice_address_company_required and not self.all_optional:
|
||||||
self.fields['name_parts'].widget.attrs['data-required-if'] = '#id_is_business_0'
|
self.fields['name_parts'].widget.attrs['data-required-if'] = '#id_is_business_0'
|
||||||
self.fields['name_parts'].widget.attrs['data-no-required-attr'] = '1'
|
self.fields['name_parts'].widget.attrs['data-no-required-attr'] = '1'
|
||||||
self.fields['company'].widget.attrs['data-required-if'] = '#id_is_business_1'
|
self.fields['company'].widget.attrs['data-required-if'] = '#id_is_business_1'
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ from pretix.presale.forms.checkout import (
|
|||||||
AddOnsForm, ContactForm, InvoiceAddressForm, InvoiceNameForm,
|
AddOnsForm, ContactForm, InvoiceAddressForm, InvoiceNameForm,
|
||||||
)
|
)
|
||||||
from pretix.presale.signals import (
|
from pretix.presale.signals import (
|
||||||
checkout_confirm_messages, checkout_flow_steps, contact_form_fields,
|
checkout_all_optional, checkout_confirm_messages, checkout_flow_steps,
|
||||||
order_meta_from_request, question_form_fields,
|
contact_form_fields, order_meta_from_request, question_form_fields,
|
||||||
)
|
)
|
||||||
from pretix.presale.views import CartMixin, get_cart, get_cart_total
|
from pretix.presale.views import CartMixin, get_cart, get_cart_total
|
||||||
from pretix.presale.views.cart import (
|
from pretix.presale.views.cart import (
|
||||||
@@ -308,6 +308,13 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
|||||||
def is_applicable(self, request):
|
def is_applicable(self, request):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def all_optional(self):
|
||||||
|
for recv, resp in checkout_all_optional.send(sender=self.request.event, request=self.request):
|
||||||
|
if resp:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def contact_form(self):
|
def contact_form(self):
|
||||||
initial = {
|
initial = {
|
||||||
@@ -320,7 +327,7 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
|||||||
return ContactForm(data=self.request.POST if self.request.method == "POST" else None,
|
return ContactForm(data=self.request.POST if self.request.method == "POST" else None,
|
||||||
event=self.request.event,
|
event=self.request.event,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
initial=initial)
|
initial=initial, all_optional=self.all_optional)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def eu_reverse_charge_relevant(self):
|
def eu_reverse_charge_relevant(self):
|
||||||
@@ -348,13 +355,13 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
|||||||
request=self.request,
|
request=self.request,
|
||||||
instance=self.invoice_address,
|
instance=self.invoice_address,
|
||||||
initial=initial,
|
initial=initial,
|
||||||
validate_vat_id=False)
|
validate_vat_id=False, all_optional=self.all_optional)
|
||||||
return InvoiceAddressForm(data=self.request.POST if self.request.method == "POST" else None,
|
return InvoiceAddressForm(data=self.request.POST if self.request.method == "POST" else None,
|
||||||
event=self.request.event,
|
event=self.request.event,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
initial=initial,
|
initial=initial,
|
||||||
instance=self.invoice_address,
|
instance=self.invoice_address,
|
||||||
validate_vat_id=self.eu_reverse_charge_relevant)
|
validate_vat_id=self.eu_reverse_charge_relevant, all_optional=self.all_optional)
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
self.request = request
|
self.request = request
|
||||||
@@ -383,23 +390,25 @@ class QuestionsStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
|||||||
self.request = request
|
self.request = request
|
||||||
try:
|
try:
|
||||||
emailval = EmailValidator()
|
emailval = EmailValidator()
|
||||||
if 'email' not in self.cart_session:
|
if not self.cart_session.get('email') and not self.all_optional:
|
||||||
if warn:
|
if warn:
|
||||||
messages.warning(request, _('Please enter a valid email address.'))
|
messages.warning(request, _('Please enter a valid email address.'))
|
||||||
return False
|
return False
|
||||||
emailval(self.cart_session.get('email'))
|
if self.cart_session.get('email'):
|
||||||
|
emailval(self.cart_session.get('email'))
|
||||||
except ValidationError:
|
except ValidationError:
|
||||||
if warn:
|
if warn:
|
||||||
messages.warning(request, _('Please enter a valid email address.'))
|
messages.warning(request, _('Please enter a valid email address.'))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if request.event.settings.invoice_address_required and (not self.invoice_address or not self.invoice_address.street):
|
if not self.all_optional:
|
||||||
messages.warning(request, _('Please enter your invoicing address.'))
|
if request.event.settings.invoice_address_required and (not self.invoice_address or not self.invoice_address.street):
|
||||||
return False
|
messages.warning(request, _('Please enter your invoicing address.'))
|
||||||
|
return False
|
||||||
|
|
||||||
if request.event.settings.invoice_name_required and (not self.invoice_address or not self.invoice_address.name):
|
if request.event.settings.invoice_name_required and (not self.invoice_address or not self.invoice_address.name):
|
||||||
messages.warning(request, _('Please enter your name.'))
|
messages.warning(request, _('Please enter your name.'))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for cp in self._positions_for_questions:
|
for cp in self._positions_for_questions:
|
||||||
answ = {
|
answ = {
|
||||||
@@ -585,6 +594,8 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def confirm_messages(self):
|
def confirm_messages(self):
|
||||||
|
if self.all_optional:
|
||||||
|
return {}
|
||||||
msgs = {}
|
msgs = {}
|
||||||
responses = checkout_confirm_messages.send(self.request.event)
|
responses = checkout_confirm_messages.send(self.request.event)
|
||||||
for receiver, response in responses:
|
for receiver, response in responses:
|
||||||
@@ -603,10 +614,17 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
|||||||
return self.get_result(request)
|
return self.get_result(request)
|
||||||
return TemplateFlowStep.get(self, request)
|
return TemplateFlowStep.get(self, request)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def all_optional(self):
|
||||||
|
for recv, resp in checkout_all_optional.send(sender=self.request.event, request=self.request):
|
||||||
|
if resp:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
self.request = request
|
self.request = request
|
||||||
|
|
||||||
if self.confirm_messages:
|
if self.confirm_messages and not self.all_optional:
|
||||||
for key, msg in self.confirm_messages.items():
|
for key, msg in self.confirm_messages.items():
|
||||||
if request.POST.get('confirm_{}'.format(key)) != 'yes':
|
if request.POST.get('confirm_{}'.format(key)) != 'yes':
|
||||||
msg = str(_('You need to check all checkboxes on the bottom of the page.'))
|
msg = str(_('You need to check all checkboxes on the bottom of the page.'))
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ class ContactForm(forms.Form):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.event = kwargs.pop('event')
|
self.event = kwargs.pop('event')
|
||||||
self.request = kwargs.pop('request')
|
self.request = kwargs.pop('request')
|
||||||
|
self.all_optional = kwargs.pop('all_optional', False)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self.event.settings.order_email_asked_twice:
|
if self.event.settings.order_email_asked_twice:
|
||||||
self.fields['email_repeat'] = forms.EmailField(
|
self.fields['email_repeat'] = forms.EmailField(
|
||||||
label=_('E-mail address (repeated)'),
|
label=_('E-mail address (repeated)'),
|
||||||
help_text=_('Please enter the same email address again to make sure you typed it correctly.')
|
help_text=_('Please enter the same email address again to make sure you typed it correctly.'),
|
||||||
)
|
)
|
||||||
|
|
||||||
if not self.request.session.get('iframe_session', False):
|
if not self.request.session.get('iframe_session', False):
|
||||||
@@ -44,10 +45,14 @@ class ContactForm(forms.Form):
|
|||||||
self.fields['email'].widget.attrs['autofocus'] = 'autofocus'
|
self.fields['email'].widget.attrs['autofocus'] = 'autofocus'
|
||||||
|
|
||||||
responses = contact_form_fields.send(self.event, request=self.request)
|
responses = contact_form_fields.send(self.event, request=self.request)
|
||||||
for r, response in sorted(responses, key=lambda r: str(r[0])):
|
for r, response in responses:
|
||||||
for key, value in response.items():
|
for key, value in response.items():
|
||||||
# We need to be this explicit, since OrderedDict.update does not retain ordering
|
# We need to be this explicit, since OrderedDict.update does not retain ordering
|
||||||
self.fields[key] = value
|
self.fields[key] = value
|
||||||
|
if self.all_optional:
|
||||||
|
for k, v in self.fields.items():
|
||||||
|
v.required = False
|
||||||
|
v.widget.is_required = False
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.event.settings.order_email_asked_twice and self.cleaned_data.get('email') and self.cleaned_data.get('email_repeat'):
|
if self.event.settings.order_email_asked_twice and self.cleaned_data.get('email') and self.cleaned_data.get('email_repeat'):
|
||||||
|
|||||||
@@ -184,3 +184,14 @@ of products.
|
|||||||
As with all plugin signals, the ``sender`` keyword argument will contain the event. The
|
As with all plugin signals, the ``sender`` keyword argument will contain the event. The
|
||||||
receivers are expected to return HTML.
|
receivers are expected to return HTML.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
checkout_all_optional = EventPluginSignal(
|
||||||
|
providing_args=['request']
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
If any receiver of this signal returns ``True``, all input fields during checkout (contact data,
|
||||||
|
invoice address, confirmations) will be optional, except for questions. Use with care!
|
||||||
|
|
||||||
|
As with all plugin signals, the ``sender`` keyword argument will contain the event. A ``request``
|
||||||
|
argument will contain the request object.
|
||||||
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user