# # This file is part of pretix (Community Edition). # # Copyright (C) 2014-2020 Raphael Michel and contributors # Copyright (C) 2020-2021 rami.io GmbH and contributors # # This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General # Public License as published by the Free Software Foundation in version 3 of the License. # # ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are # applicable granting you additional permissions and placing additional restrictions on your usage of this software. # Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive # this file, see . # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more # details. # # You should have received a copy of the GNU Affero General Public License along with this program. If not, see # . # from django.db import models from django.db.models import Q from django.utils.functional import cached_property from django.utils.timezone import now from django.utils.translation import gettext_lazy as _, pgettext_lazy from django_scopes import ScopedManager from pretix.base.media import MEDIA_TYPES from pretix.base.models import LoggedModel from pretix.base.models.customers import Customer from pretix.base.models.giftcards import GiftCard from pretix.base.models.orders import OrderPosition from pretix.base.models.organizer import Organizer class ReusableMediumQuerySet(models.QuerySet): def active(self): return self.filter( Q(expires__isnull=True) | Q(expires__gte=now()), active=True, ) class ReusableMediumQuerySetManager(ScopedManager(organizer='organizer').__class__): def __init__(self): super().__init__() self._queryset_class = ReusableMediumQuerySet def active(self): return self.get_queryset().active() class ReusableMedium(LoggedModel): id = models.BigAutoField(primary_key=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) organizer = models.ForeignKey( Organizer, related_name='reusable_media', on_delete=models.PROTECT ) type = models.CharField( verbose_name=pgettext_lazy('reusable_medium', 'Media type'), choices=((k, v) for k, v in MEDIA_TYPES.items()), max_length=100, ) identifier = models.CharField( max_length=200, verbose_name=pgettext_lazy('reusable_medium', 'Identifier'), ) active = models.BooleanField( verbose_name=_('Active'), default=True ) expires = models.DateTimeField( verbose_name=_('Expiration date'), null=True, blank=True ) customer = models.ForeignKey( Customer, null=True, blank=True, related_name='reusable_media', on_delete=models.SET_NULL, verbose_name=_('Customer account'), ) linked_orderposition = models.ForeignKey( OrderPosition, null=True, blank=True, related_name='linked_media', on_delete=models.SET_NULL, verbose_name=_('Linked ticket'), ) linked_giftcard = models.ForeignKey( GiftCard, null=True, blank=True, related_name='linked_media', on_delete=models.SET_NULL, verbose_name=_('Linked gift card'), ) info = models.JSONField( default=dict ) notes = models.TextField(verbose_name=_('Notes'), null=True, blank=True) objects = ReusableMediumQuerySetManager() @cached_property def media_type(self): return MEDIA_TYPES[self.type] @property def is_expired(self): return self.expires and self.expires > now() class Meta: unique_together = (("identifier", "type", "organizer"),) indexes = [ models.Index(fields=("updated", "id")), ] ordering = "identifier", "type", "organizer" class MediumKeySet(models.Model): organizer = models.ForeignKey('Organizer', on_delete=models.CASCADE, related_name='medium_key_sets') public_id = models.BigIntegerField( unique=True, ) media_type = models.CharField(max_length=100) active = models.BooleanField(default=True) uid_key = models.BinaryField() diversification_key = models.BinaryField() objects = ScopedManager(organizer='organizer') class Meta: constraints = [ models.UniqueConstraint( fields=["organizer", "media_type"], condition=Q(active=True), name="keyset_unique_active", ), ]