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 %}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 %} -