Sendmail: Abstract away to allow more types of recipients (#2994)

Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
Raphael Michel
2023-01-10 12:03:50 +01:00
committed by GitHub
parent d07948613a
commit 9b1d7cc522
17 changed files with 780 additions and 284 deletions

View File

@@ -70,14 +70,7 @@ class FormPlaceholderMixin:
)
class MailForm(FormPlaceholderMixin, forms.Form):
recipients = forms.ChoiceField(
label=_('Send email to'),
widget=forms.RadioSelect,
initial='orders',
choices=[]
)
sendto = forms.MultipleChoiceField() # overridden later
class BaseMailForm(FormPlaceholderMixin, forms.Form):
subject = forms.CharField(label=_("Subject"))
message = forms.CharField(label=_("Message"))
attachment = CachedFileField(
@@ -91,12 +84,100 @@ class MailForm(FormPlaceholderMixin, forms.Form):
help_text=_('Sending an attachment increases the chance of your email not arriving or being sorted into spam folders. We recommend only using PDFs '
'of no more than 2 MB in size.'),
max_size=settings.FILE_UPLOAD_MAX_SIZE_EMAIL_ATTACHMENT
) # TODO i18n
)
def __init__(self, *args, **kwargs):
event = self.event = kwargs.pop('event')
context_parameters = kwargs.pop('context_parameters')
super().__init__(*args, **kwargs)
self.fields['subject'] = I18nFormField(
label=_('Subject'),
widget=I18nTextInput, required=True,
locales=event.settings.get('locales'),
)
self.fields['message'] = I18nFormField(
label=_('Message'),
widget=I18nTextarea, required=True,
locales=event.settings.get('locales'),
)
self._set_field_placeholders('subject', context_parameters)
self._set_field_placeholders('message', context_parameters)
class WaitinglistMailForm(BaseMailForm):
items = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple(
attrs={'class': 'scrolling-multiple-choice'}
),
label=_('Only send to people who bought'),
label=pgettext_lazy('sendmail_form', 'Waiting for'),
required=True,
queryset=Item.objects.none()
)
subevent = forms.ModelChoiceField(
SubEvent.objects.none(),
label=pgettext_lazy('sendmail_form', 'Restrict to a specific event date'),
required=False,
empty_label=pgettext_lazy('subevent', 'All dates')
)
subevents_from = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('sendmail_form', 'Restrict to event dates starting at or after'),
required=False,
)
subevents_to = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('sendmail_form', 'Restrict to event dates starting before'),
required=False,
)
def clean(self):
d = super().clean()
if d.get('subevent') and (d.get('subevents_from') or d.get('subevents_to')):
raise ValidationError(pgettext_lazy('subevent', 'Please either select a specific date or a date range, not both.'))
if bool(d.get('subevents_from')) != bool(d.get('subevents_to')):
raise ValidationError(pgettext_lazy('subevent', 'If you set a date range, please set both a start and an end.'))
return d
def __init__(self, *args, **kwargs):
event = self.event = kwargs['event']
super().__init__(*args, **kwargs)
self.fields['items'].queryset = event.items.all()
if not self.initial.get('items'):
self.initial['items'] = event.items.all()
if event.has_subevents:
self.fields['subevent'].queryset = event.subevents.all()
self.fields['subevent'].widget = Select2(
attrs={
'data-model-select2': 'event',
'data-select2-url': reverse('control:event.subevents.select2', kwargs={
'event': event.slug,
'organizer': event.organizer.slug,
}),
'data-placeholder': pgettext_lazy('subevent', 'Date')
}
)
self.fields['subevent'].widget.choices = self.fields['subevent'].choices
else:
del self.fields['subevent']
del self.fields['subevents_from']
del self.fields['subevents_to']
class OrderMailForm(BaseMailForm):
recipients = forms.ChoiceField(
label=pgettext_lazy('sendmail_from', 'Send to'),
widget=forms.RadioSelect,
initial='orders',
choices=[]
)
sendto = forms.MultipleChoiceField() # overridden later
items = forms.ModelMultipleChoiceField(
widget=forms.CheckboxSelectMultiple(
attrs={'class': 'scrolling-multiple-choice'}
),
label=pgettext_lazy('sendmail_form', 'Restrict to products'),
required=True,
queryset=Item.objects.none()
)
@@ -105,31 +186,31 @@ class MailForm(FormPlaceholderMixin, forms.Form):
required=False
)
checkin_lists = SafeModelMultipleChoiceField(queryset=CheckinList.objects.none(), required=False) # overridden later
not_checked_in = forms.BooleanField(label=_("Send to customers not checked in"), required=False)
not_checked_in = forms.BooleanField(label=pgettext_lazy('sendmail_from', 'Restrict to recipients without check-in'), required=False)
subevent = forms.ModelChoiceField(
SubEvent.objects.none(),
label=_('Only send to customers of'),
label=pgettext_lazy('sendmail_form', 'Restrict to a specific event date'),
required=False,
empty_label=pgettext_lazy('subevent', 'All dates')
)
subevents_from = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('subevent', 'Only send to customers of dates starting at or after'),
label=pgettext_lazy('sendmail_form', 'Restrict to event dates starting at or after'),
required=False,
)
subevents_to = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('subevent', 'Only send to customers of dates starting before'),
label=pgettext_lazy('sendmail_form', 'Restrict to event dates starting before'),
required=False,
)
created_from = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('subevent', 'Only send to customers with orders created after'),
label=pgettext_lazy('sendmail_form', 'Restrict to orders created at or after'),
required=False,
)
created_to = forms.SplitDateTimeField(
widget=SplitDateTimePickerWidget(),
label=pgettext_lazy('subevent', 'Only send to customers with orders created before'),
label=pgettext_lazy('sendmail_form', 'Restrict to orders created before'),
required=False,
)
attach_tickets = forms.BooleanField(
@@ -147,7 +228,7 @@ class MailForm(FormPlaceholderMixin, forms.Form):
return d
def __init__(self, *args, **kwargs):
event = self.event = kwargs.pop('event')
event = self.event = kwargs['event']
super().__init__(*args, **kwargs)
recp_choices = [
@@ -161,18 +242,6 @@ class MailForm(FormPlaceholderMixin, forms.Form):
]
self.fields['recipients'].choices = recp_choices
self.fields['subject'] = I18nFormField(
label=_('Subject'),
widget=I18nTextInput, required=True,
locales=event.settings.get('locales'),
)
self.fields['message'] = I18nFormField(
label=_('Message'),
widget=I18nTextarea, required=True,
locales=event.settings.get('locales'),
)
self._set_field_placeholders('subject', ['event', 'order', 'position_or_address'])
self._set_field_placeholders('message', ['event', 'order', 'position_or_address'])
choices = [(e, l) for e, l in Order.STATUS_CHOICE if e != 'n']
choices.insert(0, ('na', _('payment pending (except unapproved)')))
choices.insert(0, ('pa', _('approval pending')))
@@ -181,7 +250,7 @@ class MailForm(FormPlaceholderMixin, forms.Form):
('overdue', _('pending with payment overdue'))
)
self.fields['sendto'] = forms.MultipleChoiceField(
label=_("Send to customers with order status"),
label=pgettext_lazy('sendmail_from', 'Restrict to orders with status'),
widget=forms.CheckboxSelectMultiple(
attrs={'class': 'scrolling-multiple-choice no-search'}
),
@@ -205,11 +274,11 @@ class MailForm(FormPlaceholderMixin, forms.Form):
'event': event.slug,
'organizer': event.organizer.slug,
}),
'data-placeholder': _('Send to customers checked in on list'),
'data-placeholder': pgettext_lazy('sendmail_from', 'Restrict to recipients with check-in on list')
}
)
self.fields['checkin_lists'].widget.choices = self.fields['checkin_lists'].choices
self.fields['checkin_lists'].label = _('Send to customers checked in on list')
self.fields['checkin_lists'].label = pgettext_lazy('sendmail_from', 'Restrict to recipients with check-in on list')
if event.has_subevents:
self.fields['subevent'].queryset = event.subevents.all()