From 8c50b7409fd50953a20180da98d002797d2fdeda Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 18 Sep 2019 21:25:22 +0200 Subject: [PATCH] Add Item.issue_giftcard --- doc/api/resources/items.rst | 6 ++++++ src/pretix/api/serializers/item.py | 2 +- .../migrations/0138_auto_20190918_1910.py | 20 +++++++++++++++++++ src/pretix/base/models/items.py | 8 ++++++++ src/pretix/control/forms/item.py | 11 ++++++++++ .../templates/pretixcontrol/item/index.html | 1 + src/tests/api/test_items.py | 9 +++++++++ 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/pretix/base/migrations/0138_auto_20190918_1910.py diff --git a/doc/api/resources/items.rst b/doc/api/resources/items.rst index ab53542bb7..617adc8824 100644 --- a/doc/api/resources/items.rst +++ b/doc/api/resources/items.rst @@ -77,6 +77,7 @@ generate_tickets boolean If ``false``, t rules apply. allow_waitinglist boolean If ``false``, no waiting list will be shown for this product when it is sold out. +issue_giftcard boolean If ``true``, buying this product will yield a gift card. show_quota_left boolean Publicly show how many tickets are still available. If this is ``null``, the event default is used. has_variations boolean Shows whether or not this item has variations. @@ -206,6 +207,7 @@ Endpoints "tax_rate": "0.00", "tax_rule": 1, "admission": false, + "issue_giftcard": false, "position": 0, "picture": null, "available_from": null, @@ -300,6 +302,7 @@ Endpoints "tax_rate": "0.00", "tax_rule": 1, "admission": false, + "issue_giftcard": false, "position": 0, "picture": null, "available_from": null, @@ -375,6 +378,7 @@ Endpoints "tax_rate": "0.00", "tax_rule": 1, "admission": false, + "issue_giftcard": false, "position": 0, "picture": null, "available_from": null, @@ -437,6 +441,7 @@ Endpoints "tax_rate": "0.00", "tax_rule": 1, "admission": false, + "issue_giftcard": false, "position": 0, "picture": null, "available_from": null, @@ -531,6 +536,7 @@ Endpoints "tax_rate": "0.00", "tax_rule": 1, "admission": false, + "issue_giftcard": false, "position": 0, "picture": null, "available_from": null, diff --git a/src/pretix/api/serializers/item.py b/src/pretix/api/serializers/item.py index 51e676ed1d..7aea644d0c 100644 --- a/src/pretix/api/serializers/item.py +++ b/src/pretix/api/serializers/item.py @@ -119,7 +119,7 @@ class ItemSerializer(I18nAwareModelSerializer): 'require_voucher', 'hide_without_voucher', 'allow_cancel', 'require_bundling', 'min_per_order', 'max_per_order', 'checkin_attention', 'has_variations', 'variations', 'addons', 'bundles', 'original_price', 'require_approval', 'generate_tickets', - 'show_quota_left', 'hidden_if_available', 'allow_waitinglist') + 'show_quota_left', 'hidden_if_available', 'allow_waitinglist', 'issue_giftcard') read_only_fields = ('has_variations', 'picture') def get_serializer_context(self): diff --git a/src/pretix/base/migrations/0138_auto_20190918_1910.py b/src/pretix/base/migrations/0138_auto_20190918_1910.py new file mode 100644 index 0000000000..d25ead6714 --- /dev/null +++ b/src/pretix/base/migrations/0138_auto_20190918_1910.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.1 on 2019-09-18 19:10 + +from django.db import migrations, models +import django.db.models.deletion +import pretix.base.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0137_auto_20190918_1820'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='issue_giftcard', + field=models.BooleanField(default=False), + ), + ] diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index e68572eb2b..31c43522b3 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -242,6 +242,8 @@ class Item(LoggedModel): :type require_approval: bool :param sales_channels: Sales channels this item is available on. :type sales_channels: bool + :param issue_giftcard: If ``True``, buying this product will give you a gift card with the value of the product's price + :type issue_giftcard: bool """ objects = ItemQuerySetManager() @@ -413,6 +415,12 @@ class Item(LoggedModel): verbose_name=_('Sales channels'), default=['web'] ) + issue_giftcard = models.BooleanField( + verbose_name=_('This product is a gift card'), + help_text=_('When a customer buys this product, they will get a gift card with a value corresponding to the ' + 'product price.'), + default=False + ) # !!! Attention: If you add new fields here, also add them to the copying code in # pretix/control/forms/item.py if applicable. diff --git a/src/pretix/control/forms/item.py b/src/pretix/control/forms/item.py index 77ec131607..b8d13d9b69 100644 --- a/src/pretix/control/forms/item.py +++ b/src/pretix/control/forms/item.py @@ -421,6 +421,16 @@ class ItemUpdateForm(I18nModelForm): self.fields['hidden_if_available'].widget.choices = self.fields['hidden_if_available'].choices self.fields['hidden_if_available'].required = False + def clean(self): + d = super().clean() + if d['issue_giftcard']: + if d['tax_rule'] and d['tax_rule'].rate > 0: + self.add_error( + 'tax_rule', + _("Gift card products should not be associated with non-zero tax rates since sales tax will be applied when the gift card is redeemed.") + ) + return d + class Meta: model = Item localized_fields = '__all__' @@ -451,6 +461,7 @@ class ItemUpdateForm(I18nModelForm): 'require_bundling', 'show_quota_left', 'hidden_if_available', + 'issue_giftcard', ] field_classes = { 'available_from': SplitDateTimeField, diff --git a/src/pretix/control/templates/pretixcontrol/item/index.html b/src/pretix/control/templates/pretixcontrol/item/index.html index eb366ae999..ec1b7ad28c 100644 --- a/src/pretix/control/templates/pretixcontrol/item/index.html +++ b/src/pretix/control/templates/pretixcontrol/item/index.html @@ -55,6 +55,7 @@
{% trans "Additional settings" %} + {% bootstrap_field form.issue_giftcard layout="control" %} {% bootstrap_field form.show_quota_left layout="control" %} {% for f in plugin_forms %} {% bootstrap_form f layout="control" %} diff --git a/src/tests/api/test_items.py b/src/tests/api/test_items.py index 73d0ecda75..1b8b6c5080 100644 --- a/src/tests/api/test_items.py +++ b/src/tests/api/test_items.py @@ -223,6 +223,7 @@ TEST_ITEM_RES = { "tax_rate": "0.00", "tax_rule": None, "admission": False, + "issue_giftcard": False, "position": 0, "generate_tickets": None, "allow_waitinglist": True, @@ -391,6 +392,7 @@ def test_item_create(token_client, organizer, event, item, category, taxrule): "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": False, "position": 0, "picture": None, "available_from": None, @@ -426,6 +428,7 @@ def test_item_create_with_variation(token_client, organizer, event, item, catego "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -476,6 +479,7 @@ def test_item_create_with_addon(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -520,6 +524,7 @@ def test_item_create_with_addon(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -562,6 +567,7 @@ def test_item_create_with_addon(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -604,6 +610,7 @@ def test_item_create_with_addon(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -654,6 +661,7 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None, @@ -699,6 +707,7 @@ def test_item_create_with_bundle(token_client, organizer, event, item, category, "tax_rate": "19.00", "tax_rule": taxrule.pk, "admission": True, + "issue_giftcard": True, "position": 0, "picture": None, "available_from": None,