add new tickets app

This commit is contained in:
Stephan Telling 2017-08-17 17:51:24 +02:00
parent c04838377b
commit bea270f8eb
No known key found for this signature in database
GPG key ID: D4892289F36ADA9B
9 changed files with 302 additions and 0 deletions

0
src/tickets/__init__.py Normal file
View file

38
src/tickets/admin.py Normal file
View file

@ -0,0 +1,38 @@
from django.contrib import admin
from .models import (
TicketType,
SponsorTicket,
DiscountTicket,
ShopTicket
)
class BaseTicketAdmin(admin.ModelAdmin):
actions = ['generate_pdf']
exclude = ['qrcode_base64']
def generate_pdf(self, request, queryset):
for ticket in queryset.all():
ticket.generate_pdf()
generate_pdf.description = 'Generate PDF for the ticket'
@admin.register(TicketType)
class TicketTypeAdmin(admin.ModelAdmin):
pass
@admin.register(SponsorTicket)
class SponsorTicketAdmin(BaseTicketAdmin):
pass
@admin.register(DiscountTicket)
class DiscountTicketAdmin(BaseTicketAdmin):
pass
@admin.register(ShopTicket)
class ShopTicketAdmin(BaseTicketAdmin):
pass

5
src/tickets/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class TicketsConfig(AppConfig):
name = 'tickets'

View file

@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-08-17 14:22
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
('shop', '0047_auto_20170522_1942'),
('camps', '0022_camp_colour'),
('sponsors', '0006_auto_20170715_1110'),
]
operations = [
migrations.CreateModel(
name='BaseTicket',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('qrcode_base64', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='TicketType',
fields=[
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('name', models.TextField()),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='DiscountTicket',
fields=[
('baseticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='tickets.BaseTicket')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('price', models.IntegerField(help_text='Price of the discounted ticket (in DKK, including VAT).')),
],
options={
'abstract': False,
},
bases=('tickets.baseticket', models.Model),
),
migrations.CreateModel(
name='ShopTicket',
fields=[
('baseticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='tickets.BaseTicket')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('name', models.CharField(blank=True, help_text='Name of the person this ticket belongs to. This can be different from the buying user.', max_length=100, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('checked_in', models.BooleanField(default=False)),
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shoptickets', to='shop.Order')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='shop.Product')),
],
options={
'abstract': False,
},
bases=('tickets.baseticket', models.Model),
),
migrations.CreateModel(
name='SponsorTicket',
fields=[
('baseticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='tickets.BaseTicket')),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('sponsor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sponsors.Sponsor')),
],
options={
'abstract': False,
},
bases=('tickets.baseticket', models.Model),
),
migrations.AddField(
model_name='baseticket',
name='camp',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camps.Camp'),
),
migrations.AddField(
model_name='baseticket',
name='ticket_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tickets.TicketType'),
),
]

View file

128
src/tickets/models.py Normal file
View file

@ -0,0 +1,128 @@
import io
import logging
import hashlib
import base64
import qrcode
from django.db import models
from django.conf import settings
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from utils.models import (
UUIDModel,
CreatedUpdatedModel
)
from shop.pdf import generate_pdf_letter
logger = logging.getLogger("bornhack.%s" % __name__)
# TicketType can be full week, one day. etc.
class TicketType(CreatedUpdatedModel, UUIDModel):
name = models.TextField()
def __str__(self):
return '{}'.format(self.name)
class BaseTicket(models.Model):
qrcode_base64 = models.TextField(null=True, blank=True)
ticket_type = models.ForeignKey('TicketType')
camp = models.ForeignKey('camps.Camp')
def save(self, **kwargs):
super(BaseTicket, self).save(**kwargs)
self.qrcode_base64 = self.get_qr_code()
super(BaseTicket, self).save(**kwargs)
def _get_token(self):
return hashlib.sha256(
'{_id}{secret_key}'.format(
_id=self.pk,
secret_key=settings.SECRET_KEY,
).encode('utf-8')
).hexdigest()
def get_qr_code(self):
qr = qrcode.make(
self._get_token(),
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H
).resize((250, 250))
file_like = io.BytesIO()
qr.save(file_like, format='png')
qrcode_base64 = base64.b64encode(file_like.getvalue())
return qrcode_base64
def get_qr_code_url(self):
return 'data:image/png;base64,{}'.format(self.qrcode_base64)
def generate_pdf(self):
generate_pdf_letter(
filename='ticket_{}.pdf'.format(self.pk),
formatdict={'ticket': self},
template='pdf/ticket.html'
)
class SponsorTicket(BaseTicket, CreatedUpdatedModel, UUIDModel):
sponsor = models.ForeignKey('sponsors.Sponsor')
def __str__(self):
return 'SponsorTicket: {}'.format(self.pk)
class DiscountTicket(BaseTicket, CreatedUpdatedModel, UUIDModel):
price = models.IntegerField(
help_text=_('Price of the discounted ticket (in DKK, including VAT).')
)
def __str__(self):
return 'DiscountTicket: {}'.format(self.pk)
class ShopTicket(BaseTicket, CreatedUpdatedModel, UUIDModel):
order = models.ForeignKey('shop.Order', related_name='shoptickets')
product = models.ForeignKey('shop.Product')
name = models.CharField(
max_length=100,
help_text=(
'Name of the person this ticket belongs to. '
'This can be different from the buying user.'
),
null=True,
blank=True,
)
email = models.EmailField(
null=True,
blank=True,
)
checked_in = models.BooleanField(default=False)
# overwrite the _get_token method because old tickets use the user_id
def _get_token(self):
return hashlib.sha256(
'{_id}{user_id}{secret_key}'.format(
_id=self.pk,
user_id=self.order.user.pk,
secret_key=settings.SECRET_KEY,
).encode('utf-8')
).hexdigest()
def __str__(self):
return 'Ticket {user} {product}'.format(
user=self.order.user,
product=self.product
)
def save(self, **kwargs):
super(ShopTicket, self).save(**kwargs)
self.qrcode_base64 = self.get_qr_code()
super(ShopTicket, self).save(**kwargs)
def get_absolute_url(self):
return str(reverse_lazy('shop:ticket_detail', kwargs={'pk': self.pk}))

0
src/tickets/pdf.py Normal file
View file

View file

@ -0,0 +1,32 @@
{% load static from staticfiles %}
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<table style="width:100%;">
<tr>
<td style="width: 75%;">&nbsp;</td>
<td>
<h3>
{{ ticket.created|date:"b jS, Y" }}<br>
</h3>
</td>
</tr>
</table>
<br>
<h2>{{ ticket.camp.title }} Ticket</h2>
<h3>Type: {{ ticket.ticket_type }}</h3>
{% if ticket.name %}
<h3>Participant: {{ ticket.name }}</h3>
<br>
{% elif ticket.order.user.email %}
<h3>Participant: {{ ticket.order.user.email }}</h3>
<br>
{% elif ticket.sponsor %}
<h3>Sponsor: {{ ticket.sponsor.name }} </h3>
<img src="{{ ticket.sponsor.logo }}"></img>
{% endif %}
<center>
<img src="{{ ticket.get_qr_code_url }}"></img>
<p>Ticket #{{ ticket.pk }}</p>
</center>

3
src/tickets/views.py Normal file
View file

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.