diff --git a/src/pretix/base/migrations/0024_auto_20160728_1725.py b/src/pretix/base/migrations/0024_auto_20160728_1725.py
new file mode 100644
index 000000000..cfa29a6a0
--- /dev/null
+++ b/src/pretix/base/migrations/0024_auto_20160728_1725.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.4 on 2016-07-28 17:25
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pretixbase', '0023_auto_20160601_1039'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='item',
+ name='hide_without_voucher',
+ field=models.BooleanField(default=False, help_text='This product will be hidden from the event page until the user enters a voucher code that is specifically tied to this product (and not via a quota).', verbose_name='This product will only be shown if a voucher is redeemed.'),
+ ),
+ migrations.AddField(
+ model_name='item',
+ name='require_voucher',
+ field=models.BooleanField(default=False, help_text='To buy this product, the user needs a voucher that applies to this product either directly or via a quota.', verbose_name='This product can only be bought using a voucher.'),
+ ),
+ ]
diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py
index 15d90e6d2..09ee726f1 100644
--- a/src/pretix/base/models/items.py
+++ b/src/pretix/base/models/items.py
@@ -173,6 +173,18 @@ class Item(LoggedModel):
null=True, blank=True,
help_text=_('This product will not be sold after the given date.')
)
+ require_voucher = models.BooleanField(
+ verbose_name=_('This product can only be bought using a voucher.'),
+ default=False,
+ help_text=_('To buy this product, the user needs a voucher that applies to this product '
+ 'either directly or via a quota.')
+ )
+ hide_without_voucher = models.BooleanField(
+ verbose_name=_('This product will only be shown if a voucher is redeemed.'),
+ default=False,
+ help_text=_('This product will be hidden from the event page until the user enters a voucher '
+ 'code that is specifically tied to this product (and not via a quota).')
+ )
class Meta:
verbose_name = _("Product")
diff --git a/src/pretix/base/services/cart.py b/src/pretix/base/services/cart.py
index b8edaafa2..fd285a4ef 100644
--- a/src/pretix/base/services/cart.py
+++ b/src/pretix/base/services/cart.py
@@ -32,7 +32,8 @@ error_messages = {
'voucher_invalid': _('This voucher code is not known in our database.'),
'voucher_redeemed': _('This voucher code has already been used an can only be used once.'),
'voucher_expired': _('This voucher is expired.'),
- 'voucher_invalid_item': _('This voucher is not valid for this item.'),
+ 'voucher_invalid_item': _('This voucher is not valid for this product.'),
+ 'voucher_required': _('You need a valid voucher code to order this product.'),
}
@@ -130,6 +131,12 @@ def _add_new_items(event: Event, items: List[dict],
if voucher and voucher.quota and voucher.quota.pk not in [q.pk for q in quotas]:
return error_messages['voucher_invalid_item']
+ if item.require_voucher and voucher is None:
+ return error_messages['voucher_required']
+
+ if item.hide_without_voucher and (voucher is None or voucher.item is None or voucher.item.pk != item.pk):
+ return error_messages['voucher_required']
+
if len(quotas) == 0 or not item.is_available():
err = err or error_messages['unavailable']
continue
diff --git a/src/pretix/control/forms/item.py b/src/pretix/control/forms/item.py
index d27c00b46..cedb9c87d 100644
--- a/src/pretix/control/forms/item.py
+++ b/src/pretix/control/forms/item.py
@@ -142,6 +142,8 @@ class ItemUpdateForm(I18nModelForm):
'tax_rate',
'available_from',
'available_until',
+ 'require_voucher',
+ 'hide_without_voucher',
]
diff --git a/src/pretix/control/templates/pretixcontrol/item/index.html b/src/pretix/control/templates/pretixcontrol/item/index.html
index 470abc4ce..556607ec5 100644
--- a/src/pretix/control/templates/pretixcontrol/item/index.html
+++ b/src/pretix/control/templates/pretixcontrol/item/index.html
@@ -23,6 +23,8 @@
{% bootstrap_field form.available_from layout="horizontal" %}
{% bootstrap_field form.available_until layout="horizontal" %}
+ {% bootstrap_field form.require_voucher layout="horizontal" %}
+ {% bootstrap_field form.hide_without_voucher layout="horizontal" %}
- {% if item.cached_availability.0 == 100 %}
+ {% if item.require_voucher %}
+
+
+ {% trans "Enter a voucher code below to buy this ticket." %}
+
+