diff --git a/src/pretix/base/migrations/0032_item_allow_cancel.py b/src/pretix/base/migrations/0032_item_allow_cancel.py new file mode 100644 index 000000000..11dbf41ac --- /dev/null +++ b/src/pretix/base/migrations/0032_item_allow_cancel.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.9 on 2016-08-22 10:23 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0031_auto_20160816_0648'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='allow_cancel', + field=models.BooleanField(default=True, help_text='Whether this product might or not be cancelled.', verbose_name='Allow a product to be cancelled'), + ), + ] diff --git a/src/pretix/base/migrations/0033_auto_20160822_1044.py b/src/pretix/base/migrations/0033_auto_20160822_1044.py new file mode 100644 index 000000000..0d1377e35 --- /dev/null +++ b/src/pretix/base/migrations/0033_auto_20160822_1044.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.9 on 2016-08-22 10:44 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0032_item_allow_cancel'), + ] + + operations = [ + migrations.AlterField( + model_name='item', + name='allow_cancel', + field=models.BooleanField(default=True, help_text='Whether this product might or not be cancelled.', verbose_name='Allow product to be cancelled'), + ), + ] diff --git a/src/pretix/base/migrations/0035_merge.py b/src/pretix/base/migrations/0035_merge.py new file mode 100644 index 000000000..5873d735f --- /dev/null +++ b/src/pretix/base/migrations/0035_merge.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.9 on 2016-08-31 21:04 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0033_auto_20160822_1044'), + ('pretixbase', '0034_auto_20160830_1952'), + ] + + operations = [ + ] diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index e5b764ee0..387cc19e3 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -186,6 +186,11 @@ class Item(LoggedModel): 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).') ) + allow_cancel = models.BooleanField( + verbose_name=_('Allow product to be cancelled'), + default=True, + help_text=_('Whether this product might or not be cancelled.') + ) class Meta: verbose_name = _("Product") diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index e477d91ef..04d1352ff 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -243,7 +243,9 @@ class Order(LoggedModel): @property def can_user_cancel(self) -> bool: - return self.event.settings.cancel_allow_user + positions = self.positions.all().select_related('item') + cancelable = all([op.item.allow_cancel for op in positions]) + return self.event.settings.cancel_allow_user and cancelable @property def is_expired_by_time(self): diff --git a/src/pretix/control/forms/item.py b/src/pretix/control/forms/item.py index cedb9c87d..3eaea4082 100644 --- a/src/pretix/control/forms/item.py +++ b/src/pretix/control/forms/item.py @@ -119,6 +119,7 @@ class ItemCreateForm(I18nModelForm): 'admission', 'default_price', 'tax_rate', + 'allow_cancel' ] @@ -144,6 +145,7 @@ class ItemUpdateForm(I18nModelForm): 'available_until', 'require_voucher', 'hide_without_voucher', + 'allow_cancel' ] diff --git a/src/pretix/control/templates/pretixcontrol/item/index.html b/src/pretix/control/templates/pretixcontrol/item/index.html index 556607ec5..b433e844c 100644 --- a/src/pretix/control/templates/pretixcontrol/item/index.html +++ b/src/pretix/control/templates/pretixcontrol/item/index.html @@ -25,6 +25,7 @@ {% bootstrap_field form.available_until layout="horizontal" %} {% bootstrap_field form.require_voucher layout="horizontal" %} {% bootstrap_field form.hide_without_voucher layout="horizontal" %} + {% bootstrap_field form.allow_cancel layout="horizontal" %}