Files
pretix_original/src/pretix/control/forms/item.py
2017-05-17 15:47:35 +02:00

290 lines
9.7 KiB
Python

import copy
from django import forms
from django.core.exceptions import ValidationError
from django.db.models import Max
from django.forms import BooleanField, ModelMultipleChoiceField
from django.forms.formsets import DELETION_FIELD_NAME
from django.utils.translation import ugettext as __, ugettext_lazy as _
from i18nfield.forms import I18nFormField, I18nTextarea
from pretix.base.forms import I18nFormSet, I18nModelForm
from pretix.base.models import (
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
)
from pretix.base.models.items import ItemAddOn
class CategoryForm(I18nModelForm):
class Meta:
model = ItemCategory
localized_fields = '__all__'
fields = [
'name',
'description',
'is_addon'
]
class QuestionForm(I18nModelForm):
question = I18nFormField(
label=_("Question"),
widget_kwargs={'attrs': {'rows': 5}},
widget=I18nTextarea
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['items'].queryset = self.instance.event.items.all()
class Meta:
model = Question
localized_fields = '__all__'
fields = [
'question',
'type',
'required',
'items'
]
widgets = {
'items': forms.CheckboxSelectMultiple,
}
class QuestionOptionForm(I18nModelForm):
class Meta:
model = QuestionOption
localized_fields = '__all__'
fields = [
'answer',
]
class QuotaForm(I18nModelForm):
def __init__(self, **kwargs):
items = kwargs['items']
del kwargs['items']
instance = kwargs.get('instance', None)
self.original_instance = copy.copy(instance) if instance else None
super().__init__(**kwargs)
if hasattr(self, 'instance') and self.instance.pk:
active_items = set(self.instance.items.all())
active_variations = set(self.instance.variations.all())
else:
active_items = set()
active_variations = set()
for item in items:
if len(item.variations.all()) > 0:
self.fields['item_%s' % item.id] = ModelMultipleChoiceField(
label=_("Activate for"),
required=False,
initial=active_variations,
queryset=item.variations.all(),
widget=forms.CheckboxSelectMultiple
)
else:
self.fields['item_%s' % item.id] = BooleanField(
label=_("Activate"),
required=False,
initial=(item in active_items)
)
class Meta:
model = Quota
localized_fields = '__all__'
fields = [
'name',
'size',
]
class ItemCreateForm(I18nModelForm):
has_variations = forms.BooleanField(label=_('The product should exist in multiple variations'),
help_text=_('Select this option e.g. for t-shirts that come in multiple sizes. '
'You can select the variations in the next step.'),
required=False)
def __init__(self, *args, **kwargs):
self.event = kwargs['event']
super().__init__(*args, **kwargs)
self.fields['category'].queryset = self.instance.event.categories.all()
self.fields['copy_from'] = forms.ModelChoiceField(
label=_("Copy product information"),
queryset=self.event.items.all(),
widget=forms.Select,
empty_label=_('Do not copy'),
required=False
)
def save(self, *args, **kwargs):
if self.cleaned_data.get('copy_from'):
self.instance.description = self.cleaned_data['copy_from'].description
self.instance.active = self.cleaned_data['copy_from'].active
self.instance.available_from = self.cleaned_data['copy_from'].available_from
self.instance.available_until = self.cleaned_data['copy_from'].available_until
self.instance.require_voucher = self.cleaned_data['copy_from'].require_voucher
self.instance.hide_without_voucher = self.cleaned_data['copy_from'].hide_without_voucher
self.instance.allow_cancel = self.cleaned_data['copy_from'].allow_cancel
self.instance.min_per_order = self.cleaned_data['copy_from'].min_per_order
self.instance.max_per_order = self.cleaned_data['copy_from'].max_per_order
self.instance.position = (self.event.items.aggregate(p=Max('position'))['p'] or 0) + 1
instance = super().save(*args, **kwargs)
if self.cleaned_data.get('has_variations'):
if self.cleaned_data.get('copy_from') and self.cleaned_data.get('copy_from').has_variations:
for variation in self.cleaned_data['copy_from'].variations.all():
ItemVariation.objects.create(item=instance, value=variation.value, active=variation.active,
position=variation.position, default_price=variation.default_price)
else:
ItemVariation.objects.create(
item=instance, value=__('Standard')
)
if self.cleaned_data.get('copy_from'):
for question in self.cleaned_data['copy_from'].questions.all():
question.items.add(instance)
return instance
class Meta:
model = Item
localized_fields = '__all__'
fields = [
'name',
'category',
'admission',
'default_price',
'tax_rate',
'allow_cancel'
]
class ItemUpdateForm(I18nModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category'].queryset = self.instance.event.categories.all()
class Meta:
model = Item
localized_fields = '__all__'
fields = [
'category',
'name',
'active',
'admission',
'description',
'picture',
'default_price',
'free_price',
'tax_rate',
'available_from',
'available_until',
'require_voucher',
'hide_without_voucher',
'allow_cancel',
'max_per_order',
'min_per_order',
]
widgets = {
'available_from': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'available_until': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
}
class ItemVariationsFormSet(I18nFormSet):
def clean(self):
super().clean()
for f in self.forms:
if hasattr(f, '_delete_fail'):
f.fields['DELETE'].initial = False
f.fields['DELETE'].disabled = True
raise ValidationError(
message=_('The variation "%s" cannot be deleted because it has already been ordered by a user or '
'currently is in a users\'s cart. Please set the variation as "inactive" instead.'),
params=(str(f.instance),)
)
def _should_delete_form(self, form):
should_delete = super()._should_delete_form(form)
if should_delete and (form.instance.orderposition_set.exists() or form.instance.cartposition_set.exists()):
form._delete_fail = True
return False
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
class ItemVariationForm(I18nModelForm):
class Meta:
model = ItemVariation
localized_fields = '__all__'
fields = [
'value',
'active',
'default_price',
'description',
]
class ItemAddOnsFormSet(I18nFormSet):
def __init__(self, *args, **kwargs):
self.event = kwargs.get('event')
super().__init__(*args, **kwargs)
def _construct_form(self, i, **kwargs):
kwargs['event'] = self.event
return super()._construct_form(i, **kwargs)
def clean(self):
super().clean()
categories = set()
for i in range(0, self.total_form_count()):
form = self.forms[i]
if self.can_delete:
if self._should_delete_form(form):
# This form is going to be deleted so any of its errors
# should not cause the entire formset to be invalid.
continue
if form.cleaned_data['addon_category'] in categories:
raise ValidationError(_('You added the same add-on category twice'))
categories.add(form.cleaned_data['addon_category'])
@property
def empty_form(self):
self.is_valid()
form = self.form(
auto_id=self.auto_id,
prefix=self.add_prefix('__prefix__'),
empty_permitted=True,
locales=self.locales,
event=self.event
)
self.add_fields(form, None)
return form
class ItemAddOnForm(I18nModelForm):
def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event')
super().__init__(*args, **kwargs)
self.fields['addon_category'].queryset = self.event.categories.all()
class Meta:
model = ItemAddOn
localized_fields = '__all__'
fields = [
'addon_category',
'min_count',
'max_count',
]
help_texts = {
'min_count': _('Be aware that setting a minimal number makes it impossible to buy this product if all '
'available add-ons are sold out.')
}