forked from CGM_Public/pretix_original
Allow to create vouchers for *all* products (#1504)
This commit is contained in:
@@ -54,7 +54,8 @@ class VoucherSerializer(I18nAwareModelSerializer):
|
||||
|
||||
Voucher.clean_item_properties(
|
||||
full_data, self.context.get('event'),
|
||||
full_data.get('quota'), full_data.get('item'), full_data.get('variation')
|
||||
full_data.get('quota'), full_data.get('item'), full_data.get('variation'),
|
||||
block_quota=full_data.get('block_quota')
|
||||
)
|
||||
Voucher.clean_subevent(
|
||||
full_data, self.context.get('event')
|
||||
|
||||
@@ -175,8 +175,6 @@ def filter_available(qs, channel='web', voucher=None, allow_addons=False):
|
||||
q &= Q(pk=voucher.item_id)
|
||||
elif voucher.quota_id:
|
||||
q &= Q(quotas__in=[voucher.quota_id])
|
||||
else:
|
||||
return qs.none()
|
||||
if not voucher or not voucher.show_hidden_items:
|
||||
q &= Q(hide_without_voucher=False)
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ class Voucher(LoggedModel):
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def clean_item_properties(data, event, quota, item, variation, seats_given=False):
|
||||
def clean_item_properties(data, event, quota, item, variation, block_quota=False, seats_given=False):
|
||||
if quota:
|
||||
if quota.event != event:
|
||||
raise ValidationError(_('You cannot select a quota that belongs to a different event.'))
|
||||
@@ -241,8 +241,12 @@ class Voucher(LoggedModel):
|
||||
'Otherwise it might be unclear which quotas to block.'))
|
||||
if item.category and item.category.is_addon:
|
||||
raise ValidationError(_('It is currently not possible to create vouchers for add-on products.'))
|
||||
elif not seats_given:
|
||||
raise ValidationError(_('You need to specify either a quota or a product.'))
|
||||
elif block_quota:
|
||||
raise ValidationError(_('You need to select a specific product or quota if this voucher should reserve '
|
||||
'tickets.'))
|
||||
elif variation:
|
||||
raise ValidationError(_('You cannot select a variation without having selected a product that provides '
|
||||
'variations.'))
|
||||
|
||||
@staticmethod
|
||||
def clean_max_usages(data, redeemed):
|
||||
@@ -331,7 +335,8 @@ class Voucher(LoggedModel):
|
||||
elif item and not item.has_variations:
|
||||
avail = item.check_quotas(ignored_quotas=old_quotas, subevent=data.get('subevent'))
|
||||
else:
|
||||
raise ValidationError(_('You need to specify either a quota or a product.'))
|
||||
raise ValidationError(_('You need to select a specific product or quota if this voucher should reserve '
|
||||
'tickets.'))
|
||||
|
||||
if avail[0] != Quota.AVAILABILITY_OK or (avail[1] is not None and avail[1] < cnt):
|
||||
raise ValidationError(_('You cannot create a voucher that blocks quota as the selected product or '
|
||||
@@ -410,7 +415,9 @@ class Voucher(LoggedModel):
|
||||
return item.quotas.filter(pk=self.quota_id).exists()
|
||||
if self.item_id and not self.variation_id:
|
||||
return self.item_id == item.pk
|
||||
return (self.item_id == item.pk) and (variation and self.variation_id == variation.pk)
|
||||
if self.item_id:
|
||||
return (self.item_id == item.pk) and (variation and self.variation_id == variation.pk)
|
||||
return True
|
||||
|
||||
def is_active(self):
|
||||
"""
|
||||
|
||||
@@ -109,9 +109,10 @@ class VoucherForm(I18nModelForm):
|
||||
'event': instance.event.slug,
|
||||
'organizer': instance.event.organizer.slug,
|
||||
}),
|
||||
'data-placeholder': ''
|
||||
'data-placeholder': _('All products')
|
||||
}
|
||||
)
|
||||
self.fields['itemvar'].required = False
|
||||
self.fields['itemvar'].widget.choices = self.fields['itemvar'].choices
|
||||
|
||||
if self.instance.event.seating_plan or self.instance.event.subevents.filter(seating_plan__isnull=False).exists():
|
||||
@@ -123,9 +124,6 @@ class VoucherForm(I18nModelForm):
|
||||
initial=self.instance.seat.seat_guid if self.instance.seat else '',
|
||||
help_text=str(self.instance.seat) if self.instance.seat else '',
|
||||
)
|
||||
self.fields['itemvar'].required = False
|
||||
else:
|
||||
self.fields['itemvar'].required = True
|
||||
|
||||
def clean(self):
|
||||
data = super().clean()
|
||||
@@ -165,7 +163,8 @@ class VoucherForm(I18nModelForm):
|
||||
Voucher.clean_item_properties(
|
||||
data, self.instance.event,
|
||||
self.instance.quota, self.instance.item, self.instance.variation,
|
||||
seats_given=data.get('seat') or data.get('seats')
|
||||
seats_given=data.get('seat') or data.get('seats'),
|
||||
block_quota=data.get('block_quota')
|
||||
)
|
||||
if not self.instance.show_hidden_items and (
|
||||
(self.instance.quota and all(i.hide_without_voucher for i in self.instance.quota.items.all()))
|
||||
|
||||
@@ -75,7 +75,7 @@ event_permission_sub_urls = [
|
||||
('delete', 'can_change_event_settings', 'taxrules/1/', 404),
|
||||
('get', 'can_view_vouchers', 'vouchers/', 200),
|
||||
('get', 'can_view_vouchers', 'vouchers/1/', 404),
|
||||
('post', 'can_change_vouchers', 'vouchers/', 400),
|
||||
('post', 'can_change_vouchers', 'vouchers/', 201),
|
||||
('put', 'can_change_vouchers', 'vouchers/1/', 404),
|
||||
('patch', 'can_change_vouchers', 'vouchers/1/', 404),
|
||||
('delete', 'can_change_vouchers', 'vouchers/1/', 404),
|
||||
|
||||
@@ -251,9 +251,13 @@ def create_voucher(token_client, organizer, event, data, expected_failure=False)
|
||||
def test_voucher_require_item(token_client, organizer, event, item):
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={},
|
||||
data={'block_quota': True},
|
||||
expected_failure=True
|
||||
)
|
||||
create_voucher(
|
||||
token_client, organizer, event,
|
||||
data={},
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -717,6 +717,14 @@ class VoucherTestCase(BaseQuotaTestCase):
|
||||
self.assertTrue(v.applies_to(self.var1.item, self.var1))
|
||||
self.assertFalse(v.applies_to(self.var1.item, self.var2))
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_voucher_applicability_all(self):
|
||||
v = Voucher.objects.create(event=self.event)
|
||||
self.assertTrue(v.applies_to(self.item1))
|
||||
self.assertTrue(v.applies_to(self.var1.item))
|
||||
self.assertTrue(v.applies_to(self.var1.item, self.var1))
|
||||
self.assertTrue(v.applies_to(self.var1.item, self.var2))
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_voucher_applicability_variation_through_quota(self):
|
||||
self.quota.variations.add(self.var1)
|
||||
|
||||
Reference in New Issue
Block a user