Adding a badge token to tickets that grant that.
This commit is contained in:
parent
04d858adf3
commit
b7feb96c9b
|
@ -298,7 +298,8 @@ class Order(CreatedUpdatedModel):
|
||||||
def is_partially_ticket_generated(self):
|
def is_partially_ticket_generated(self):
|
||||||
if (
|
if (
|
||||||
self.orderproductrelation_set.filter(ticket_generated=True).count() != 0
|
self.orderproductrelation_set.filter(ticket_generated=True).count() != 0
|
||||||
and self.orderproductrelation_set.filter(ticket_generated=False).count() != 0
|
and self.orderproductrelation_set.filter(ticket_generated=False).count()
|
||||||
|
!= 0
|
||||||
):
|
):
|
||||||
# some products are handed out, others are not
|
# some products are handed out, others are not
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -1,33 +1,29 @@
|
||||||
# Generated by Django 2.2.2 on 2019-07-18 18:52
|
# Generated by Django 2.2.2 on 2019-07-18 18:52
|
||||||
import hashlib
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
from tickets.models import create_ticket_token
|
||||||
|
|
||||||
|
|
||||||
def save_tokens(apps, schema_editor):
|
def save_tokens(apps, schema_editor):
|
||||||
ShopTicket = apps.get_model('tickets', 'ShopTicket')
|
ShopTicket = apps.get_model("tickets", "ShopTicket")
|
||||||
SponsorTicket = apps.get_model('tickets', 'SponsorTicket')
|
SponsorTicket = apps.get_model("tickets", "SponsorTicket")
|
||||||
DiscountTicket = apps.get_model('tickets', 'DiscountTicket')
|
DiscountTicket = apps.get_model("tickets", "DiscountTicket")
|
||||||
|
|
||||||
for model in (ShopTicket, SponsorTicket, DiscountTicket):
|
for model in (ShopTicket, SponsorTicket, DiscountTicket):
|
||||||
|
|
||||||
for ticket in model.objects.all():
|
for ticket in model.objects.all():
|
||||||
token = hashlib.sha256(
|
token = create_ticket_token(
|
||||||
"{_id}{secret_key}".format(
|
"{_id}{secret_key}".format(
|
||||||
_id=ticket.uuid, secret_key=settings.SECRET_KEY
|
_id=ticket.uuid, secret_key=settings.SECRET_KEY
|
||||||
).encode("utf-8")
|
).encode("utf-8")
|
||||||
).hexdigest()
|
)
|
||||||
ticket.token = token
|
ticket.token = token
|
||||||
ticket.save()
|
ticket.save()
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [("tickets", "0006_auto_20190616_1746")]
|
||||||
('tickets', '0006_auto_20190616_1746'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
operations = [migrations.RunPython(save_tokens)]
|
||||||
migrations.RunPython(save_tokens)
|
|
||||||
]
|
|
||||||
|
|
18
src/tickets/migrations/0009_tickettype_includes_badge.py
Normal file
18
src/tickets/migrations/0009_tickettype_includes_badge.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.2.3 on 2019-07-23 20:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0008_auto_20190718_2055'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='tickettype',
|
||||||
|
name='includes_badge',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
28
src/tickets/migrations/0010_auto_20190724_2037.py
Normal file
28
src/tickets/migrations/0010_auto_20190724_2037.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 2.2.3 on 2019-07-24 18:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0009_tickettype_includes_badge'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='discountticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='shopticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sponsorticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64, null=True),
|
||||||
|
),
|
||||||
|
]
|
29
src/tickets/migrations/0011_save_badge_token_to_db.py
Normal file
29
src/tickets/migrations/0011_save_badge_token_to_db.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 2.2.3 on 2019-07-24 18:37
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
from tickets.models import create_ticket_token
|
||||||
|
|
||||||
|
|
||||||
|
def save_badge_tokens(apps, schema_editor):
|
||||||
|
ShopTicket = apps.get_model("tickets", "ShopTicket")
|
||||||
|
SponsorTicket = apps.get_model("tickets", "SponsorTicket")
|
||||||
|
DiscountTicket = apps.get_model("tickets", "DiscountTicket")
|
||||||
|
|
||||||
|
for model in (ShopTicket, SponsorTicket, DiscountTicket):
|
||||||
|
|
||||||
|
for ticket in model.objects.all():
|
||||||
|
badge_token = create_ticket_token(
|
||||||
|
"{_id}{secret_key}-badge".format(
|
||||||
|
_id=ticket.uuid, secret_key=settings.SECRET_KEY
|
||||||
|
).encode("utf-8")
|
||||||
|
)
|
||||||
|
ticket.badge_token = badge_token
|
||||||
|
ticket.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [("tickets", "0010_auto_20190724_2037")]
|
||||||
|
|
||||||
|
operations = [migrations.RunPython(save_badge_tokens)]
|
28
src/tickets/migrations/0012_auto_20190724_2037.py
Normal file
28
src/tickets/migrations/0012_auto_20190724_2037.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 2.2.3 on 2019-07-24 18:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0011_save_badge_token_to_db'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='discountticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='shopticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='sponsorticket',
|
||||||
|
name='badge_token',
|
||||||
|
field=models.CharField(max_length=64),
|
||||||
|
),
|
||||||
|
]
|
|
@ -17,16 +17,32 @@ logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
class TicketType(CampRelatedModel, UUIDModel):
|
class TicketType(CampRelatedModel, UUIDModel):
|
||||||
name = models.TextField()
|
name = models.TextField()
|
||||||
camp = models.ForeignKey("camps.Camp", on_delete=models.PROTECT)
|
camp = models.ForeignKey("camps.Camp", on_delete=models.PROTECT)
|
||||||
|
includes_badge = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{} ({})".format(self.name, self.camp.title)
|
return "{} ({})".format(self.name, self.camp.title)
|
||||||
|
|
||||||
|
|
||||||
|
def create_ticket_token(string):
|
||||||
|
return hashlib.sha256(string).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def qr_code_base64(token):
|
||||||
|
qr = qrcode.make(
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
class BaseTicket(CampRelatedModel, UUIDModel):
|
class BaseTicket(CampRelatedModel, UUIDModel):
|
||||||
ticket_type = models.ForeignKey("TicketType", on_delete=models.PROTECT)
|
ticket_type = models.ForeignKey("TicketType", on_delete=models.PROTECT)
|
||||||
used = models.BooleanField(default=False)
|
used = models.BooleanField(default=False)
|
||||||
badge_handed_out = models.BooleanField(default=False)
|
badge_handed_out = models.BooleanField(default=False)
|
||||||
token = models.CharField(max_length=64)
|
token = models.CharField(max_length=64)
|
||||||
|
badge_token = models.CharField(max_length=64)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
@ -37,29 +53,31 @@ class BaseTicket(CampRelatedModel, UUIDModel):
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
self.token = self._get_token()
|
self.token = self._get_token()
|
||||||
|
self.badge_token = self._get_token()
|
||||||
super().save(**kwargs)
|
super().save(**kwargs)
|
||||||
|
|
||||||
def _get_token(self):
|
def _get_token(self):
|
||||||
return hashlib.sha256(
|
return create_ticket_token(
|
||||||
"{_id}{secret_key}".format(
|
"{_id}{secret_key}".format(
|
||||||
_id=self.uuid, secret_key=settings.SECRET_KEY
|
_id=self.uuid, secret_key=settings.SECRET_KEY
|
||||||
).encode("utf-8")
|
).encode("utf-8")
|
||||||
).hexdigest()
|
)
|
||||||
|
|
||||||
def get_qr_code_base64(self):
|
def _get_badge_token(self):
|
||||||
qr = qrcode.make(
|
return create_ticket_token(
|
||||||
self._get_token(),
|
"{_id}{secret_key}-badge".format(
|
||||||
version=1,
|
_id=self.uuid, secret_key=settings.SECRET_KEY
|
||||||
error_correction=qrcode.constants.ERROR_CORRECT_H,
|
).encode("utf-8")
|
||||||
).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):
|
def get_qr_code_url(self):
|
||||||
return "data:image/png;base64,{}".format(
|
return "data:image/png;base64,{}".format(
|
||||||
self.get_qr_code_base64().decode("utf-8")
|
qr_code_base64(self._get_token()).decode("utf-8")
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_qr_badge_code_url(self):
|
||||||
|
return "data:image/png;base64,{}".format(
|
||||||
|
qr_code_base64(self._get_badge_token()).decode("utf-8")
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_pdf(self):
|
def generate_pdf(self):
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
{% load static from staticfiles %}
|
{% load static from staticfiles %}
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
|
||||||
<table style="width:100%;">
|
<table style="width:100%;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="width: 75%;"> </td>
|
<td style="width: 75%;"> </td>
|
||||||
|
@ -25,11 +24,38 @@
|
||||||
<h3>Sponsor: {{ ticket.sponsor.name }} </h3>
|
<h3>Sponsor: {{ ticket.sponsor.name }} </h3>
|
||||||
<img src="{% static 'img/sponsors/' %}{{ sponsor.logo_filename }}"></img>
|
<img src="{% static 'img/sponsors/' %}{{ sponsor.logo_filename }}"></img>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if ticket.used %}
|
{% if ticket.used %}
|
||||||
<h2>This ticket has been used.</h2>
|
<h2>This ticket has been used.</h2>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<center>
|
<center>
|
||||||
<img src="{{ ticket.get_qr_code_url }}"></img>
|
<img src="{{ ticket.get_qr_code_url }}"></img>
|
||||||
<p>Ticket #{{ ticket.pk }}</p>
|
<p>{{ ticket.token }}</p>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
{% if ticket.ticket_type.includes_badge %}
|
||||||
|
<div style="display:block; clear:both; page-break-after:always;"></div>
|
||||||
|
|
||||||
|
<table style="width:100%;">
|
||||||
|
<tr>
|
||||||
|
<td style="width: 75%;"> </td>
|
||||||
|
<td>
|
||||||
|
<h3>
|
||||||
|
{{ ticket.created|date:"b jS, Y" }}<br>
|
||||||
|
</h3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<h2>Badge voucher</h2>
|
||||||
|
|
||||||
|
<center>
|
||||||
|
<img src="{{ ticket.get_qr_badge_code_url }}"></img>
|
||||||
|
<p>{{ ticket.badge_token }}</p>
|
||||||
|
</center>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
|
||||||
def generate_pdf_letter(filename, template, formatdict):
|
def generate_pdf_letter(filename, template, formatdict):
|
||||||
logger.debug("Generating PDF with filename %s and template %s" % (filename, template))
|
logger.debug(
|
||||||
|
"Generating PDF with filename %s and template %s" % (filename, template)
|
||||||
|
)
|
||||||
|
|
||||||
# conjure up a fake request for PDFTemplateResponse
|
# conjure up a fake request for PDFTemplateResponse
|
||||||
request = RequestFactory().get("/")
|
request = RequestFactory().get("/")
|
||||||
|
@ -47,9 +49,9 @@ def generate_pdf_letter(filename, template, formatdict):
|
||||||
|
|
||||||
# add the watermark to all pages
|
# add the watermark to all pages
|
||||||
for pagenum in range(pdfreader.getNumPages()):
|
for pagenum in range(pdfreader.getNumPages()):
|
||||||
page = watermark.getPage(0)
|
page = pdfreader.getPage(pagenum)
|
||||||
try:
|
try:
|
||||||
page.mergePage(pdfreader.getPage(pagenum))
|
page.mergePage(watermark.getPage(0))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# watermark pdf might be broken?
|
# watermark pdf might be broken?
|
||||||
return False
|
return False
|
||||||
|
@ -65,4 +67,3 @@ def generate_pdf_letter(filename, template, formatdict):
|
||||||
returnfile = io.BytesIO()
|
returnfile = io.BytesIO()
|
||||||
finalpdf.write(returnfile)
|
finalpdf.write(returnfile)
|
||||||
return returnfile
|
return returnfile
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue