commit
e828bc9c4a
|
@ -42,6 +42,7 @@ INSTALLED_APPS = [
|
||||||
'ircbot',
|
'ircbot',
|
||||||
'teams',
|
'teams',
|
||||||
'people',
|
'people',
|
||||||
|
'tickets',
|
||||||
|
|
||||||
'allauth',
|
'allauth',
|
||||||
'allauth.account',
|
'allauth.account',
|
||||||
|
|
|
@ -10,6 +10,7 @@ admin.site.register(models.CoinifyAPIRequest)
|
||||||
admin.site.register(models.Invoice)
|
admin.site.register(models.Invoice)
|
||||||
admin.site.register(models.CreditNote)
|
admin.site.register(models.CreditNote)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.CustomOrder)
|
@admin.register(models.CustomOrder)
|
||||||
class CustomOrderAdmin(admin.ModelAdmin):
|
class CustomOrderAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
|
@ -25,6 +26,7 @@ class CustomOrderAdmin(admin.ModelAdmin):
|
||||||
'paid',
|
'paid',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.ProductCategory)
|
@admin.register(models.ProductCategory)
|
||||||
class ProductCategoryAdmin(admin.ModelAdmin):
|
class ProductCategoryAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
|
@ -37,6 +39,7 @@ class ProductAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
'name',
|
'name',
|
||||||
'category',
|
'category',
|
||||||
|
'ticket_type',
|
||||||
'price',
|
'price',
|
||||||
'available_in',
|
'available_in',
|
||||||
]
|
]
|
||||||
|
@ -115,7 +118,6 @@ class TicketModelAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
list_filter = ['product', 'checked_in']
|
list_filter = ['product', 'checked_in']
|
||||||
|
|
||||||
|
|
||||||
actions = ['mark_as_arrived']
|
actions = ['mark_as_arrived']
|
||||||
|
|
||||||
def mark_as_arrived(self, request, queryset):
|
def mark_as_arrived(self, request, queryset):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from shop.pdf import generate_pdf_letter
|
from utils.pdf import generate_pdf_letter
|
||||||
from shop.email import add_invoice_email, add_creditnote_email
|
from shop.email import add_invoice_email, add_creditnote_email
|
||||||
from shop.models import Order, CustomOrder, Invoice, CreditNote
|
from shop.models import Order, CustomOrder, Invoice, CreditNote
|
||||||
import logging
|
import logging
|
||||||
|
|
22
src/shop/migrations/0048_product_ticket_type.py
Normal file
22
src/shop/migrations/0048_product_ticket_type.py
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# -*- 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
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tickets', '0001_initial'),
|
||||||
|
('shop', '0047_auto_20170522_1942'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='product',
|
||||||
|
name='ticket_type',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='tickets.TicketType'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,21 +1,28 @@
|
||||||
|
import io
|
||||||
|
import logging
|
||||||
|
import hashlib
|
||||||
|
import base64
|
||||||
|
import qrcode
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.aggregates import Sum
|
from django.db.models.aggregates import Sum
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.postgres.fields import DateTimeRangeField, JSONField
|
from django.contrib.postgres.fields import DateTimeRangeField, JSONField
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.urlresolvers import reverse_lazy
|
from django.core.urlresolvers import reverse_lazy
|
||||||
from utils.models import UUIDModel, CreatedUpdatedModel
|
|
||||||
from .managers import ProductQuerySet, OrderQuerySet
|
|
||||||
import hashlib, io, base64, qrcode
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from unidecode import unidecode
|
from unidecode import unidecode
|
||||||
from django.utils.dateparse import parse_datetime
|
from django.utils.dateparse import parse_datetime
|
||||||
from django.utils import timezone
|
|
||||||
|
from utils.models import UUIDModel, CreatedUpdatedModel
|
||||||
|
from tickets.models import ShopTicket
|
||||||
|
from .managers import ProductQuerySet, OrderQuerySet
|
||||||
|
|
||||||
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
|
||||||
class CustomOrder(CreatedUpdatedModel):
|
class CustomOrder(CreatedUpdatedModel):
|
||||||
|
@ -77,7 +84,7 @@ class Order(CreatedUpdatedModel):
|
||||||
CREDIT_CARD = 'credit_card'
|
CREDIT_CARD = 'credit_card'
|
||||||
BLOCKCHAIN = 'blockchain'
|
BLOCKCHAIN = 'blockchain'
|
||||||
BANK_TRANSFER = 'bank_transfer'
|
BANK_TRANSFER = 'bank_transfer'
|
||||||
CASH = 'cash'
|
CASH = 'cash'
|
||||||
|
|
||||||
PAYMENT_METHODS = [
|
PAYMENT_METHODS = [
|
||||||
CREDIT_CARD,
|
CREDIT_CARD,
|
||||||
|
@ -115,7 +122,6 @@ class Order(CreatedUpdatedModel):
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
objects = OrderQuerySet.as_manager()
|
objects = OrderQuerySet.as_manager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -176,7 +182,8 @@ class Order(CreatedUpdatedModel):
|
||||||
for order_product in self.orderproductrelation_set.all():
|
for order_product in self.orderproductrelation_set.all():
|
||||||
if order_product.product.category.name == "Tickets":
|
if order_product.product.category.name == "Tickets":
|
||||||
for _ in range(0, order_product.quantity):
|
for _ in range(0, order_product.quantity):
|
||||||
ticket = Ticket(
|
ticket = ShopTicket(
|
||||||
|
ticket_type=order_product.product.ticket_type,
|
||||||
order=self,
|
order=self,
|
||||||
product=order_product.product,
|
product=order_product.product,
|
||||||
)
|
)
|
||||||
|
@ -291,6 +298,12 @@ class Product(CreatedUpdatedModel, UUIDModel):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ticket_type = models.ForeignKey(
|
||||||
|
'tickets.TicketType',
|
||||||
|
null=True,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
|
||||||
objects = ProductQuerySet.as_manager()
|
objects = ProductQuerySet.as_manager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -514,4 +527,3 @@ class Ticket(CreatedUpdatedModel, UUIDModel):
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return str(reverse_lazy('shop:ticket_detail', kwargs={'pk': self.pk}))
|
return str(reverse_lazy('shop:ticket_detail', kwargs={'pk': self.pk}))
|
||||||
|
|
||||||
|
|
0
src/tickets/__init__.py
Normal file
0
src/tickets/__init__.py
Normal file
38
src/tickets/admin.py
Normal file
38
src/tickets/admin.py
Normal 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
5
src/tickets/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class TicketsConfig(AppConfig):
|
||||||
|
name = 'tickets'
|
96
src/tickets/migrations/0001_initial.py
Normal file
96
src/tickets/migrations/0001_initial.py
Normal 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'),
|
||||||
|
),
|
||||||
|
]
|
0
src/tickets/migrations/__init__.py
Normal file
0
src/tickets/migrations/__init__.py
Normal file
128
src/tickets/models.py
Normal file
128
src/tickets/models.py
Normal 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 utils.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
0
src/tickets/pdf.py
Normal file
32
src/tickets/templates/pdf/ticket.html
Normal file
32
src/tickets/templates/pdf/ticket.html
Normal 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%;"> </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
3
src/tickets/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -48,6 +48,7 @@ class Command(BaseCommand):
|
||||||
timezone.datetime(2016, 9, 4, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2016, 9, 4, 12, 0, tzinfo=timezone.utc),
|
||||||
timezone.datetime(2016, 9, 6, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2016, 9, 6, 12, 0, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
|
colour='#000000',
|
||||||
)
|
)
|
||||||
|
|
||||||
camp2017 = Camp.objects.create(
|
camp2017 = Camp.objects.create(
|
||||||
|
@ -66,6 +67,7 @@ class Command(BaseCommand):
|
||||||
timezone.datetime(2017, 9, 4, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2017, 9, 4, 12, 0, tzinfo=timezone.utc),
|
||||||
timezone.datetime(2017, 9, 6, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2017, 9, 6, 12, 0, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
|
colour='#000000',
|
||||||
)
|
)
|
||||||
|
|
||||||
camp2018 = Camp.objects.create(
|
camp2018 = Camp.objects.create(
|
||||||
|
@ -84,6 +86,7 @@ class Command(BaseCommand):
|
||||||
timezone.datetime(2018, 9, 4, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2018, 9, 4, 12, 0, tzinfo=timezone.utc),
|
||||||
timezone.datetime(2018, 9, 6, 12, 0, tzinfo=timezone.utc),
|
timezone.datetime(2018, 9, 6, 12, 0, tzinfo=timezone.utc),
|
||||||
),
|
),
|
||||||
|
colour='#000000',
|
||||||
)
|
)
|
||||||
|
|
||||||
self.output("Creating users...")
|
self.output("Creating users...")
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
import logging
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from wkhtmltopdf.views import PDFTemplateResponse
|
from wkhtmltopdf.views import PDFTemplateResponse
|
||||||
from PyPDF2 import PdfFileWriter, PdfFileReader
|
from PyPDF2 import PdfFileWriter, PdfFileReader
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import logging
|
|
||||||
import io
|
|
||||||
import os
|
|
||||||
logger = logging.getLogger("bornhack.%s" % __name__)
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +37,14 @@ def generate_pdf_letter(filename, template, formatdict):
|
||||||
|
|
||||||
# get watermark from watermark file
|
# get watermark from watermark file
|
||||||
watermark = PdfFileReader(
|
watermark = PdfFileReader(
|
||||||
open(os.path.join(settings.STATICFILES_DIRS[0], 'pdf', settings.PDF_LETTERHEAD_FILENAME), 'rb')
|
open(
|
||||||
|
os.path.join(
|
||||||
|
settings.STATICFILES_DIRS[0],
|
||||||
|
'pdf',
|
||||||
|
settings.PDF_LETTERHEAD_FILENAME
|
||||||
|
),
|
||||||
|
'rb'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# add the watermark to all pages
|
# add the watermark to all pages
|
||||||
|
@ -60,4 +68,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