diff --git a/src/pretix/base/migrations/0135_auto_20190910_2020.py b/src/pretix/base/migrations/0135_auto_20190910_2020.py new file mode 100644 index 000000000..33d55371b --- /dev/null +++ b/src/pretix/base/migrations/0135_auto_20190910_2020.py @@ -0,0 +1,47 @@ +# Generated by Django 2.2.1 on 2019-09-10 20:20 + +from django.db import migrations, models +import django.db.models.deletion +import pretix.base.models.fields +import pretix.base.models.giftcards + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0134_auto_20190909_1042'), + ] + + operations = [ + migrations.CreateModel( + name='GiftCard', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('issuance', models.DateTimeField(auto_now_add=True)), + ('secret', models.CharField(db_index=True, default=pretix.base.models.giftcards.gen_giftcard_secret, max_length=190, unique=True)), + ('currency', models.CharField(max_length=10)), + ('issued_in', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards', to='pretixbase.OrderPosition')), + ('issuer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='issued_gift_cards', to='pretixbase.Organizer')), + ], + ), + migrations.CreateModel( + name='GiftCardTransaction', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('datetime', models.DateTimeField(auto_now_add=True)), + ('value', models.DecimalField(decimal_places=2, max_digits=10)), + ('card', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='pretixbase.GiftCard')), + ('order', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='gift_card_transactions', to='pretixbase.Order')), + ('payment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='gift_card_transactions', to='pretixbase.OrderPayment')), + ('refund', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='gift_card_transactions', to='pretixbase.OrderRefund')), + ], + ), + migrations.CreateModel( + name='GiftCardAcceptance', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('collector', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gift_card_issuer_acceptance', to='pretixbase.Organizer')), + ('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gift_card_collector_acceptance', to='pretixbase.Organizer')), + ], + ), + ] diff --git a/src/pretix/base/models/__init__.py b/src/pretix/base/models/__init__.py index 22175ed9f..2793d22b2 100644 --- a/src/pretix/base/models/__init__.py +++ b/src/pretix/base/models/__init__.py @@ -7,6 +7,7 @@ from .event import ( Event, Event_SettingsStore, EventLock, EventMetaProperty, EventMetaValue, RequiredAction, SubEvent, SubEventMetaValue, generate_invite_token, ) +from .giftcards import GiftCard, GiftCardAcceptance, GiftCardTransaction from .invoices import Invoice, InvoiceLine, invoice_filename from .items import ( Item, ItemAddOn, ItemBundle, ItemCategory, ItemVariation, Question, diff --git a/src/pretix/base/models/giftcards.py b/src/pretix/base/models/giftcards.py new file mode 100644 index 000000000..ac68d6cdb --- /dev/null +++ b/src/pretix/base/models/giftcards.py @@ -0,0 +1,90 @@ +from decimal import Decimal + +from django.conf import settings +from django.db import models +from django.db.models import Sum +from django.utils.crypto import get_random_string + + +def gen_giftcard_secret(): + charset = list('ABCDEFGHJKLMNPQRSTUVWXYZ3789') + while True: + code = get_random_string(length=settings.ENTROPY['giftcard_secret'], allowed_chars=charset) + if not GiftCard.objects.filter(secret=code).exists(): + return code + + +class GiftCardAcceptance(models.Model): + issuer = models.ForeignKey( + 'Organizer', + related_name='gift_card_collector_acceptance', + on_delete=models.CASCADE + ) + collector = models.ForeignKey( + 'Organizer', + related_name='gift_card_issuer_acceptance', + on_delete=models.CASCADE + ) + + +class GiftCard(models.Model): + issuer = models.ForeignKey( + 'Organizer', + related_name='issued_gift_cards', + on_delete=models.PROTECT, + ) + issued_in = models.ForeignKey( + 'OrderPosition', + related_name='issued_gift_cards', + on_delete=models.PROTECT, + ) + issuance = models.DateTimeField( + auto_now_add=True, + ) + secret = models.CharField( + max_length=190, + default=gen_giftcard_secret, + unique=True, + db_index=True, + ) + currency = models.CharField(max_length=10) + + @property + def value(self): + return self.transactions.aggregate(s=Sum('value'))['s'] or Decimal('0.00') + + +class GiftCardTransaction(models.Model): + card = models.ForeignKey( + 'GiftCard', + related_name='transactions', + on_delete=models.PROTECT + ) + datetime = models.DateTimeField( + auto_now_add=True + ) + value = models.DecimalField( + decimal_places=2, + max_digits=10 + ) + order = models.ForeignKey( + 'Order', + related_name='gift_card_transactions', + null=True, + blank=True, + on_delete=models.PROTECT + ) + payment = models.ForeignKey( + 'OrderPayment', + related_name='gift_card_transactions', + null=True, + blank=True, + on_delete=models.PROTECT + ) + refund = models.ForeignKey( + 'OrderRefund', + related_name='gift_card_transactions', + null=True, + blank=True, + on_delete=models.PROTECT + ) diff --git a/src/pretix/settings.py b/src/pretix/settings.py index 4dd418060..dbc6ccbdc 100644 --- a/src/pretix/settings.py +++ b/src/pretix/settings.py @@ -241,6 +241,7 @@ ENTROPY = { 'order_code': config.getint('entropy', 'order_code', fallback=5), 'ticket_secret': config.getint('entropy', 'ticket_secret', fallback=32), 'voucher_code': config.getint('entropy', 'voucher_code', fallback=16), + 'giftcard_secret': config.getint('entropy', 'giftcard_secret', fallback=16), } # Internal settings