Allow to create vouchers for *all* products (#1504)

This commit is contained in:
Raphael Michel
2019-11-27 14:57:09 +01:00
committed by GitHub
parent 530632d624
commit bbc70447a2
7 changed files with 32 additions and 15 deletions

View File

@@ -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')

View File

@@ -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)

View File

@@ -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):
"""

View File

@@ -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()))

View File

@@ -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),

View File

@@ -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

View File

@@ -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)