Пример #1
0
class ScheduleRoomForm(I18nFormMixin, forms.Form):
    room = SafeModelMultipleChoiceField(
        label=_("Rooms"),
        required=False,
        queryset=Room.objects.none(),
        widget=forms.SelectMultiple(attrs={
            "class": "select2",
            "data-placeholder": _("Rooms")
        }),
    )

    def __init__(self, *args, event=None, **kwargs):
        self.event = event
        super().__init__(*args, **kwargs)
        self.fields["room"].queryset = self.event.rooms.all()
Пример #2
0
class ReminderFilterForm(QuestionFilterForm):
    questions = SafeModelMultipleChoiceField(
        Question.objects.none(),
        required=False,
        help_text=_("If you select no question, all questions will be used."),
        label=_("Questions"),
    )

    def get_question_queryset(self):
        return Question.objects.filter(
            event=self.event,
            target__in=["speaker", "submission"],
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["questions"].queryset = self.get_question_queryset()
Пример #3
0
class ReminderFilterForm(QuestionFilterForm):
    questions = SafeModelMultipleChoiceField(
        Question.objects.none(),
        required=False,
        help_text=_("If you select no question, all questions will be used."),
        label=_("Questions"),
    )

    def get_question_queryset(self):
        # We want to exclude questions with "freeze after", the deadlines of which have passed
        return Question.objects.filter(
            event=self.event,
            target__in=["speaker", "submission"],
        ).exclude(freeze_after__lt=timezone.now())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["questions"].queryset = self.get_question_queryset()
Пример #4
0
class MailForm(forms.Form):
    recipients = forms.ChoiceField(label=_('Send email to'),
                                   widget=forms.RadioSelect,
                                   initial='orders',
                                   choices=[])
    sendto = forms.MultipleChoiceField()  # overridden later
    subject = forms.CharField(label=_("Subject"))
    message = forms.CharField(label=_("Message"))
    attachment = CachedFileField(
        label=_("Attachment"),
        required=False,
        ext_whitelist=(".png", ".jpg", ".gif", ".jpeg", ".pdf", ".txt",
                       ".docx", ".gif", ".svg", ".pptx", ".ppt", ".doc",
                       ".xlsx", ".xls", ".jfif", ".heic", ".heif", ".pages",
                       ".bmp", ".tif", ".tiff"),
        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=10 * 1024 * 1024)  # TODO i18n
    items = forms.ModelMultipleChoiceField(
        widget=forms.CheckboxSelectMultiple(
            attrs={'class': 'scrolling-multiple-choice'}),
        label=_('Only send to people who bought'),
        required=True,
        queryset=Item.objects.none())
    filter_checkins = forms.BooleanField(label=_('Filter check-in status'),
                                         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)
    subevent = forms.ModelChoiceField(SubEvent.objects.none(),
                                      label=_('Only send to customers of'),
                                      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'),
        required=False,
    )
    subevents_to = forms.SplitDateTimeField(
        widget=SplitDateTimePickerWidget(),
        label=pgettext_lazy('subevent',
                            'Only send to customers of dates starting before'),
        required=False,
    )

    def clean(self):
        d = super().clean()
        if d.get('subevent') and d.get('subevents_from'):
            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 _set_field_placeholders(self, fn, base_parameters):
        phs = [
            '{%s}' % p for p in sorted(
                get_available_placeholders(self.event, base_parameters).keys())
        ]
        ht = _('Available placeholders: {list}').format(list=', '.join(phs))
        if self.fields[fn].help_text:
            self.fields[fn].help_text += ' ' + str(ht)
        else:
            self.fields[fn].help_text = ht
        self.fields[fn].validators.append(PlaceholderValidator(phs))

    def __init__(self, *args, **kwargs):
        event = self.event = kwargs.pop('event')
        super().__init__(*args, **kwargs)

        recp_choices = [('orders', _('Everyone who created a ticket order'))]
        if event.settings.attendee_emails_asked:
            recp_choices += [
                ('attendees',
                 _('Every attendee (falling back to the order contact when no attendee email address is '
                   'given)')),
                ('both',
                 _('Both (all order contact addresses and all attendee email addresses)'
                   ))
            ]
        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')))
        if not event.settings.get('payment_term_expire_automatically',
                                  as_type=bool):
            choices.append(('overdue', _('pending with payment overdue')))
        self.fields['sendto'] = forms.MultipleChoiceField(
            label=_("Send to customers with order status"),
            widget=forms.CheckboxSelectMultiple(
                attrs={'class': 'scrolling-multiple-choice'}),
            choices=choices)
        if not self.initial.get('sendto'):
            self.initial['sendto'] = ['p', 'na']
        elif 'n' in self.initial['sendto']:
            self.initial['sendto'].append('pa')
            self.initial['sendto'].append('na')

        self.fields['items'].queryset = event.items.all()
        if not self.initial.get('items'):
            self.initial['items'] = event.items.all()

        self.fields['checkin_lists'].queryset = event.checkin_lists.all()
        self.fields['checkin_lists'].widget = Select2Multiple(
            attrs={
                'data-model-select2':
                'generic',
                'data-select2-url':
                reverse('control:event.orders.checkinlists.select2',
                        kwargs={
                            'event': event.slug,
                            'organizer': event.organizer.slug,
                        }),
                'data-placeholder':
                _('Send to customers checked 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')

        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']
Пример #5
0
class StretchgoalsSettingsForm(I18nForm, SettingsForm):
    # General settings
    stretchgoals_start_date = forms.DateField(
        required=False,
        label=_('Start date'),
        widget=DatePickerWidget(),
        help_text=_('Will start at first sale by default.'),
    )
    stretchgoals_end_date = forms.DateField(
        required=False,
        label=_('End date'),
        widget=DatePickerWidget(),
        help_text=_('Will end at last sale by default.'),
    )
    stretchgoals_items = SafeModelMultipleChoiceField(
        queryset=Item.objects.none(),
        required=False,
        label=_('Item types'),
        help_text=_('Items to be included in the calculation.'),
        widget=forms.CheckboxSelectMultiple,
    )
    stretchgoals_include_pending = forms.BooleanField(
        required=False,
        label=_('Include pending orders'),
        help_text=_(
            'By default, only paid orders are included in the calculation.'),
    )

    # Goal settings
    stretchgoals_new_name = I18nFormField(required=False,
                                          label=_('New goal\'s name'),
                                          widget=I18nTextInput)
    stretchgoals_new_total = forms.IntegerField(
        required=False, min_value=0, label=_('New total revenue goal'))
    stretchgoals_new_amount = forms.IntegerField(
        required=False,
        min_value=0,
        label=_('New goal\'s amount of items to be sold'))
    stretchgoals_new_description = I18nFormField(
        required=False,
        label=_('New goal\'s description'),
        widget=I18nTextarea)

    # Display settings
    stretchgoals_is_public = forms.BooleanField(
        required=False,
        label=_('Show publicly'),
        help_text=_('By default, the chart is only shown in the backend.'),
    )
    stretchgoals_calculation_text = forms.BooleanField(
        required=False,
        label=_('Show public text'),
        help_text=
        _('This text will include the current state and extrapolations for all goals.'
          ),
    )
    stretchgoals_chart_averages = forms.BooleanField(
        required=False,
        label=_('Generate average price graph'),
        help_text=_(
            'This graph shows the development of the average price paid.'),
    )
    stretchgoals_chart_totals = forms.BooleanField(
        required=False,
        label=_('Generate total revenue graph'),
        help_text=_('This graph shows the total revenue over time.'),
    )
    stretchgoals_chart_itemsales = forms.BooleanField(
        required=False,
        label=_('Generate sold items graph'),
        help_text=_(
            'This graph shows the total amount of sold items over time.'),
    )
    stretchgoals_show_itemsales_items = forms.BooleanField(
        required=False,
        label=_('Show individual products in sold items graph'),
        help_text=_(
            'If this option is disabled, an aggregated number will only be shown in the sold items graph.'
            'Else, a per-item breakdown will be displayed'),
        widget=forms.CheckboxInput(
            attrs={
                'data-checkbox-dependency': '#id_stretchgoals_chart_itemsales'
            }),
    )
    stretchgoals_min_orders = forms.IntegerField(
        required=False,
        label=_('Minimal number of orders'),
        help_text=
        _('Only show the graph if more than this many orders are taken into consideration.'
          ),
    )
    stretchgoals_public_text = I18nFormField(
        required=False,
        label=_('Text shown on the public page'),
        help_text=_(
            'Text shown on the public page. You can use the placeholder '
            '{avg_now} (the current average).'),
        widget=I18nTextarea,
    )

    def __init__(self, *args, **kwargs):
        """ Reduce possible friends_ticket_items to items of this event. """
        self.event = kwargs.pop('event')
        super().__init__(*args, **kwargs)

        initial_items = (self.event.settings.get('stretchgoals_items',
                                                 as_type=QuerySet) or [])
        if isinstance(initial_items, str) and initial_items:
            initial_items = self.event.items.filter(
                id__in=initial_items.split(','))
        elif isinstance(initial_items, list):
            initial_items = self.event.items.filter(
                id__in=[i.pk for i in initial_items])

        self.fields['stretchgoals_items'].queryset = Item.objects.filter(
            event=self.event)
        self.initial['stretchgoals_items'] = initial_items
        self.goals = get_goals(self.event)

    def _save_new_goal(self):
        goals = json.loads(
            self.event.settings.get('stretchgoals_goals') or "[]")
        new_goal = dict()
        for item in ['name', 'total', 'amount', 'description']:
            new_goal[item] = self.cleaned_data.pop(
                'stretchgoals_new_{}'.format(item))
            self.fields.pop('stretchgoals_new_{}'.format(item))

        if new_goal['total']:
            goals.append(new_goal)
            set_goals(self.event, goals)

    def save(self, *args, **kwargs):
        self._save_new_goal()
        self.event.settings._h.add_type(
            QuerySet, lambda queryset: ','.join(
                [str(element.pk) for element in queryset]),
            lambda pk_list: Item.objects.filter(pk__in=list(
                filter(None, pk_list.split(',')))))
        super().save(*args, **kwargs)
Пример #6
0
class MailForm(forms.Form):
    recipients = forms.ChoiceField(label=_('Send email to'),
                                   widget=forms.RadioSelect,
                                   initial='orders',
                                   choices=[])
    sendto = forms.MultipleChoiceField()  # overridden later
    subject = forms.CharField(label=_("Subject"))
    message = forms.CharField(label=_("Message"))
    items = forms.ModelMultipleChoiceField(
        widget=forms.CheckboxSelectMultiple(
            attrs={'class': 'scrolling-multiple-choice'}),
        label=_('Only send to people who bought'),
        required=True,
        queryset=Item.objects.none())
    filter_checkins = forms.BooleanField(label=_('Filter check-in status'),
                                         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)
    subevent = forms.ModelChoiceField(SubEvent.objects.none(),
                                      label=_('Only send to customers of'),
                                      required=False,
                                      empty_label=pgettext_lazy(
                                          'subevent', 'All dates'))

    def _set_field_placeholders(self, fn, base_parameters):
        phs = [
            '{%s}' % p for p in sorted(
                get_available_placeholders(self.event, base_parameters).keys())
        ]
        ht = _('Available placeholders: {list}').format(list=', '.join(phs))
        if self.fields[fn].help_text:
            self.fields[fn].help_text += ' ' + str(ht)
        else:
            self.fields[fn].help_text = ht
        self.fields[fn].validators.append(PlaceholderValidator(phs))

    def __init__(self, *args, **kwargs):
        event = self.event = kwargs.pop('event')
        super().__init__(*args, **kwargs)

        recp_choices = [('orders', _('Everyone who created a ticket order'))]
        if event.settings.attendee_emails_asked:
            recp_choices += [
                ('attendees',
                 _('Every attendee (falling back to the order contact when no attendee email address is '
                   'given)')),
                ('both',
                 _('Both (all order contact addresses and all attendee email addresses)'
                   ))
            ]
        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 = list(Order.STATUS_CHOICE)
        if not event.settings.get('payment_term_expire_automatically',
                                  as_type=bool):
            choices.append(('overdue', _('pending with payment overdue')))
        self.fields['sendto'] = forms.MultipleChoiceField(
            label=_("Send to customers with order status"),
            widget=forms.CheckboxSelectMultiple(
                attrs={'class': 'scrolling-multiple-choice'}),
            choices=choices)
        if not self.initial.get('sendto'):
            self.initial['sendto'] = ['p', 'n']

        self.fields['items'].queryset = event.items.all()
        if not self.initial.get('items'):
            self.initial['items'] = event.items.all()

        self.fields['checkin_lists'].queryset = event.checkin_lists.all()
        self.fields['checkin_lists'].widget = Select2Multiple(
            attrs={
                'data-model-select2':
                'generic',
                'data-select2-url':
                reverse('control:event.orders.checkinlists.select2',
                        kwargs={
                            'event': event.slug,
                            'organizer': event.organizer.slug,
                        }),
                'data-placeholder':
                _('Send to customers checked in on list'),
                'data-inverse-dependency':
                '#id_not_checked_in'
            })
        self.fields['checkin_lists'].widget.choices = self.fields[
            'checkin_lists'].choices
        self.fields['checkin_lists'].label = _(
            'Send to customers checked in on list')

        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']