From d994fc674a2dc08b4f6f35a2b001a0b76018268e Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 11 Jul 2019 12:33:42 +0200 Subject: [PATCH] Do not CASCADE-delete vouchers when deleting items or quotas --- src/pretix/base/models/items.py | 5 +++ src/pretix/base/models/vouchers.py | 17 ++++--- .../templates/pretixcontrol/item/delete.html | 13 ++++++ .../pretixcontrol/items/quota_delete.html | 45 +++++++++++++------ .../pretixcontrol/vouchers/index.html | 2 +- src/pretix/control/views/item.py | 4 +- 6 files changed, 66 insertions(+), 20 deletions(-) diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index 70afbf6fd7..260828e625 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -174,6 +174,8 @@ 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) @@ -411,6 +413,7 @@ class Item(LoggedModel): self.event.cache.clear() def delete(self, *args, **kwargs): + self.vouchers.update(item=None, variation=None, quota=None) super().delete(*args, **kwargs) if self.event: self.event.cache.clear() @@ -655,6 +658,7 @@ class ItemVariation(models.Model): return t def delete(self, *args, **kwargs): + self.vouchers.update(item=None, variation=None, quota=None) super().delete(*args, **kwargs) if self.item: self.item.event.cache.clear() @@ -1275,6 +1279,7 @@ class Quota(LoggedModel): return self.name def delete(self, *args, **kwargs): + self.vouchers.update(item=None, variation=None, quota=None) super().delete(*args, **kwargs) if self.event: self.event.cache.clear() diff --git a/src/pretix/base/models/vouchers.py b/src/pretix/base/models/vouchers.py index 4c694b585a..ca0b156cdb 100644 --- a/src/pretix/base/models/vouchers.py +++ b/src/pretix/base/models/vouchers.py @@ -142,22 +142,26 @@ class Voucher(LoggedModel): item = models.ForeignKey( Item, related_name='vouchers', verbose_name=_("Product"), - null=True, blank=True, on_delete=models.CASCADE, + null=True, blank=True, + on_delete=models.PROTECT, # We use a fake version of SET_NULL in Item.delete() help_text=_( "This product is added to the user's cart if the voucher is redeemed." ) ) variation = models.ForeignKey( ItemVariation, related_name='vouchers', - null=True, blank=True, on_delete=models.CASCADE, + null=True, blank=True, + on_delete=models.PROTECT, # We use a fake version of SET_NULL in ItemVariation.delete() to avoid the semantic change + # that would happen if we just set variation to None verbose_name=_("Product variation"), help_text=_( "This variation of the product select above is being used." ) ) quota = models.ForeignKey( - Quota, related_name='quota', - null=True, blank=True, on_delete=models.CASCADE, + Quota, related_name='vouchers', + null=True, blank=True, + on_delete=models.PROTECT, # We use a fake version of SET_NULL in Quota.delete() verbose_name=_("Quota"), help_text=_( "If enabled, the voucher is valid for any product affected by this quota." @@ -408,4 +412,7 @@ class Voucher(LoggedModel): kwargs['subevent'] = self.subevent if self.quota_id: return SeatCategoryMapping.objects.filter(product__quotas__pk=self.quota_id, **kwargs).exists() - return self.item.seat_category_mappings.filter(**kwargs).exists() + elif self.item_id: + return self.item.seat_category_mappings.filter(**kwargs).exists() + else: + return False diff --git a/src/pretix/control/templates/pretixcontrol/item/delete.html b/src/pretix/control/templates/pretixcontrol/item/delete.html index c2930718a0..d8f3689010 100644 --- a/src/pretix/control/templates/pretixcontrol/item/delete.html +++ b/src/pretix/control/templates/pretixcontrol/item/delete.html @@ -17,6 +17,19 @@ {% csrf_token %} {% if possible %}

{% blocktrans %}Are you sure you want to delete the product {{ item }}?{% endblocktrans %}

+ {% if vouchers %} +
+ {% blocktrans trimmed count count=vouchers %} + That will cause {{ count }} voucher to be unusable. + {% plural %} + That will cause {{ count }} voucher to be unusable. + {% endblocktrans %} + + {% trans "Show affected vouchers" %} + +
+ {% endif %} {% else %}

{% blocktrans %}You cannot delete the product {{ item }} because it already has been ordered, but you can deactivate it.{% endblocktrans %}

{% endif %} diff --git a/src/pretix/control/templates/pretixcontrol/items/quota_delete.html b/src/pretix/control/templates/pretixcontrol/items/quota_delete.html index 2b8175f0ba..d8d1f483c6 100644 --- a/src/pretix/control/templates/pretixcontrol/items/quota_delete.html +++ b/src/pretix/control/templates/pretixcontrol/items/quota_delete.html @@ -3,23 +3,42 @@ {% load bootstrap3 %} {% block title %}{% trans "Delete quota" %}{% endblock %} {% block inside %} -

{% trans "Delete quota" %}

-
- {% csrf_token %} -

{% blocktrans %}Are you sure you want to delete the quota {{ quota }}?{% endblocktrans %}

- {% if dependent|length > 0 %} -

{% blocktrans %}The following products might be no longer available for sale:{% endblocktrans %}

- {% for item in dependent %} -
  • {{ item.name }}
  • - {% endfor %} - {% endif %} -
    +

    {% trans "Delete quota" %}

    + + {% csrf_token %} +

    {% blocktrans %}Are you sure you want to delete the quota {{ quota }}?{% endblocktrans %}

    + {% if dependent|length > 0 %} +
    +

    {% blocktrans %}The following products might be no longer available for sale:{% endblocktrans %}

    + +
    + {% endif %} + {% if vouchers %} +
    + {% blocktrans trimmed count count=vouchers %} + That will cause {{ count }} voucher to be unusable. + {% plural %} + That will cause {{ count }} voucher to be unusable. + {% endblocktrans %} + + {% trans "Show affected vouchers" %} + +
    + {% endif %} +
    {% trans "Cancel" %} -
    - +
    + {% endblock %} diff --git a/src/pretix/control/templates/pretixcontrol/vouchers/index.html b/src/pretix/control/templates/pretixcontrol/vouchers/index.html index b3ae312318..9d5e820407 100644 --- a/src/pretix/control/templates/pretixcontrol/vouchers/index.html +++ b/src/pretix/control/templates/pretixcontrol/vouchers/index.html @@ -128,7 +128,7 @@ {% if v.variation %} – {{ v.variation }} {% endif %} - {% else %} + {% elif v.quota %} {% blocktrans trimmed with quota=v.quota.name %} Any product in quota "{{ quota }}" {% endblocktrans %} diff --git a/src/pretix/control/views/item.py b/src/pretix/control/views/item.py index 04cbd24d3c..7edd9e8b5b 100644 --- a/src/pretix/control/views/item.py +++ b/src/pretix/control/views/item.py @@ -771,7 +771,8 @@ class QuotaDelete(EventPermissionRequiredMixin, DeleteView): def get_context_data(self, *args, **kwargs) -> dict: context = super().get_context_data(*args, **kwargs) - context['dependent'] = list(self.get_object().items.all()) + context['dependent'] = list(self.object.items.all()) + context['vouchers'] = self.object.vouchers.count() return context @transaction.atomic @@ -1183,6 +1184,7 @@ class ItemDelete(EventPermissionRequiredMixin, DeleteView): def get_context_data(self, *args, **kwargs) -> dict: context = super().get_context_data(*args, **kwargs) context['possible'] = self.is_allowed() + context['vouchers'] = self.object.vouchers.count() return context def is_allowed(self) -> bool: