From c04838377b8dbe7d6815eda306a6f2ad8fc2c929 Mon Sep 17 00:00:00 2001 From: Stephan Telling Date: Tue, 15 Aug 2017 14:19:06 +0200 Subject: [PATCH 1/5] remove imports and ticket class from shop --- src/shop/models.py | 64 ---------------------------------------------- 1 file changed, 64 deletions(-) diff --git a/src/shop/models.py b/src/shop/models.py index e0d6e687..65d4ed08 100644 --- a/src/shop/models.py +++ b/src/shop/models.py @@ -3,19 +3,16 @@ from django.db import models from django.db.models.aggregates import Sum from django.contrib import messages from django.contrib.postgres.fields import DateTimeRangeField, JSONField -from django.http import HttpResponse from django.utils.text import slugify from django.utils.translation import ugettext_lazy as _ from django.utils import timezone 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 datetime import timedelta from unidecode import unidecode from django.utils.dateparse import parse_datetime -from django.utils import timezone class CustomOrder(CreatedUpdatedModel): @@ -454,64 +451,3 @@ class CoinifyAPIRequest(CreatedUpdatedModel): def __str__(self): return 'order %s api request %s' % (self.order.id, self.method) - - -class Ticket(CreatedUpdatedModel, UUIDModel): - order = models.ForeignKey('shop.Order', related_name='tickets') - product = models.ForeignKey('shop.Product', related_name='tickets') - qrcode_base64 = models.TextField(null=True, blank=True) - - 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) - - def __str__(self): - return 'Ticket {user} {product}'.format( - user=self.order.user, - product=self.product - ) - - def save(self, **kwargs): - super(Ticket, self).save(**kwargs) - self.qrcode_base64 = self.get_qr_code() - super(Ticket, self).save(**kwargs) - - def get_token(self): - return hashlib.sha256( - '{ticket_id}{user_id}{secret_key}'.format( - ticket_id=self.pk, - user_id=self.order.user.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 get_absolute_url(self): - return str(reverse_lazy('shop:ticket_detail', kwargs={'pk': self.pk})) - From bea270f8eb65d96ea817e07b2df5cbb1eb6f78f0 Mon Sep 17 00:00:00 2001 From: Stephan Telling Date: Thu, 17 Aug 2017 17:51:24 +0200 Subject: [PATCH 2/5] add new tickets app --- src/tickets/__init__.py | 0 src/tickets/admin.py | 38 ++++++++ src/tickets/apps.py | 5 + src/tickets/migrations/0001_initial.py | 96 +++++++++++++++++++ src/tickets/migrations/__init__.py | 0 src/tickets/models.py | 128 +++++++++++++++++++++++++ src/tickets/pdf.py | 0 src/tickets/templates/pdf/ticket.html | 32 +++++++ src/tickets/views.py | 3 + 9 files changed, 302 insertions(+) create mode 100644 src/tickets/__init__.py create mode 100644 src/tickets/admin.py create mode 100644 src/tickets/apps.py create mode 100644 src/tickets/migrations/0001_initial.py create mode 100644 src/tickets/migrations/__init__.py create mode 100644 src/tickets/models.py create mode 100644 src/tickets/pdf.py create mode 100644 src/tickets/templates/pdf/ticket.html create mode 100644 src/tickets/views.py diff --git a/src/tickets/__init__.py b/src/tickets/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/tickets/admin.py b/src/tickets/admin.py new file mode 100644 index 00000000..2939c751 --- /dev/null +++ b/src/tickets/admin.py @@ -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 diff --git a/src/tickets/apps.py b/src/tickets/apps.py new file mode 100644 index 00000000..3ea742ac --- /dev/null +++ b/src/tickets/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TicketsConfig(AppConfig): + name = 'tickets' diff --git a/src/tickets/migrations/0001_initial.py b/src/tickets/migrations/0001_initial.py new file mode 100644 index 00000000..bd4e36b5 --- /dev/null +++ b/src/tickets/migrations/0001_initial.py @@ -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'), + ), + ] diff --git a/src/tickets/migrations/__init__.py b/src/tickets/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/tickets/models.py b/src/tickets/models.py new file mode 100644 index 00000000..923d9ff7 --- /dev/null +++ b/src/tickets/models.py @@ -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})) diff --git a/src/tickets/pdf.py b/src/tickets/pdf.py new file mode 100644 index 00000000..e69de29b diff --git a/src/tickets/templates/pdf/ticket.html b/src/tickets/templates/pdf/ticket.html new file mode 100644 index 00000000..556c7d4a --- /dev/null +++ b/src/tickets/templates/pdf/ticket.html @@ -0,0 +1,32 @@ +{% load static from staticfiles %} + + + + + + + +
  +

+ {{ ticket.created|date:"b jS, Y" }}
+

+
+
+

{{ ticket.camp.title }} Ticket

+

Type: {{ ticket.ticket_type }}

+ +{% if ticket.name %} +

Participant: {{ ticket.name }}

+
+{% elif ticket.order.user.email %} +

Participant: {{ ticket.order.user.email }}

+
+{% elif ticket.sponsor %} +

Sponsor: {{ ticket.sponsor.name }}

+ +{% endif %} + +
+ +

Ticket #{{ ticket.pk }}

+
diff --git a/src/tickets/views.py b/src/tickets/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/src/tickets/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From 5eedb8ff031d4bc49204f75a08ba36b08d2ab701 Mon Sep 17 00:00:00 2001 From: Stephan Telling Date: Thu, 17 Aug 2017 17:52:22 +0200 Subject: [PATCH 3/5] update INSTALLED_APPS. add ticket_type and re-add old Ticket model also updates bootstrap script with ticket_type --- src/bornhack/settings.py | 1 + src/shop/admin.py | 4 +- src/shop/models.py | 86 +++++++++++++++++-- src/shop/pdf.py | 17 ++-- .../management/commands/bootstrap-devsite.py | 3 + 5 files changed, 100 insertions(+), 11 deletions(-) diff --git a/src/bornhack/settings.py b/src/bornhack/settings.py index d8c3e20d..1ea67e0d 100644 --- a/src/bornhack/settings.py +++ b/src/bornhack/settings.py @@ -42,6 +42,7 @@ INSTALLED_APPS = [ 'ircbot', 'teams', 'people', + 'tickets', 'allauth', 'allauth.account', diff --git a/src/shop/admin.py b/src/shop/admin.py index cb68b1f2..56520184 100644 --- a/src/shop/admin.py +++ b/src/shop/admin.py @@ -10,6 +10,7 @@ admin.site.register(models.CoinifyAPIRequest) admin.site.register(models.Invoice) admin.site.register(models.CreditNote) + @admin.register(models.CustomOrder) class CustomOrderAdmin(admin.ModelAdmin): list_display = [ @@ -25,6 +26,7 @@ class CustomOrderAdmin(admin.ModelAdmin): 'paid', ] + @admin.register(models.ProductCategory) class ProductCategoryAdmin(admin.ModelAdmin): list_display = [ @@ -37,6 +39,7 @@ class ProductAdmin(admin.ModelAdmin): list_display = [ 'name', 'category', + 'ticket_type', 'price', 'available_in', ] @@ -115,7 +118,6 @@ class TicketModelAdmin(admin.ModelAdmin): list_filter = ['product', 'checked_in'] - actions = ['mark_as_arrived'] def mark_as_arrived(self, request, queryset): diff --git a/src/shop/models.py b/src/shop/models.py index 65d4ed08..5b314554 100644 --- a/src/shop/models.py +++ b/src/shop/models.py @@ -1,3 +1,9 @@ +import io +import logging +import hashlib +import base64 +import qrcode + from django.conf import settings from django.db import models from django.db.models.aggregates import Sum @@ -7,13 +13,17 @@ from django.utils.text import slugify from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from django.core.urlresolvers import reverse_lazy -from utils.models import UUIDModel, CreatedUpdatedModel -from .managers import ProductQuerySet, OrderQuerySet from decimal import Decimal from datetime import timedelta from unidecode import unidecode from django.utils.dateparse import parse_datetime +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): text = models.TextField( @@ -74,7 +84,7 @@ class Order(CreatedUpdatedModel): CREDIT_CARD = 'credit_card' BLOCKCHAIN = 'blockchain' BANK_TRANSFER = 'bank_transfer' - CASH = 'cash' + CASH = 'cash' PAYMENT_METHODS = [ CREDIT_CARD, @@ -112,7 +122,6 @@ class Order(CreatedUpdatedModel): blank=True, ) - objects = OrderQuerySet.as_manager() def __str__(self): @@ -173,7 +182,8 @@ class Order(CreatedUpdatedModel): for order_product in self.orderproductrelation_set.all(): if order_product.product.category.name == "Tickets": for _ in range(0, order_product.quantity): - ticket = Ticket( + ticket = ShopTicket( + ticket_type=order_product.product.ticket_type, order=self, product=order_product.product, ) @@ -288,6 +298,12 @@ class Product(CreatedUpdatedModel, UUIDModel): ) ) + ticket_type = models.ForeignKey( + 'tickets.TicketType', + null=True, + blank=True + ) + objects = ProductQuerySet.as_manager() def __str__(self): @@ -451,3 +467,63 @@ class CoinifyAPIRequest(CreatedUpdatedModel): def __str__(self): return 'order %s api request %s' % (self.order.id, self.method) + + +class Ticket(CreatedUpdatedModel, UUIDModel): + order = models.ForeignKey('shop.Order', related_name='tickets') + product = models.ForeignKey('shop.Product', related_name='tickets') + qrcode_base64 = models.TextField(null=True, blank=True) + + 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) + + def __str__(self): + return 'Ticket {user} {product}'.format( + user=self.order.user, + product=self.product + ) + + def save(self, **kwargs): + super(Ticket, self).save(**kwargs) + self.qrcode_base64 = self.get_qr_code() + super(Ticket, self).save(**kwargs) + + def get_token(self): + return hashlib.sha256( + '{ticket_id}{user_id}{secret_key}'.format( + ticket_id=self.pk, + user_id=self.order.user.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 get_absolute_url(self): + return str(reverse_lazy('shop:ticket_detail', kwargs={'pk': self.pk})) diff --git a/src/shop/pdf.py b/src/shop/pdf.py index 32cafc92..1d943d94 100644 --- a/src/shop/pdf.py +++ b/src/shop/pdf.py @@ -1,11 +1,12 @@ +import logging +import io +import os + from django.contrib.auth.models import AnonymousUser from wkhtmltopdf.views import PDFTemplateResponse from PyPDF2 import PdfFileWriter, PdfFileReader from django.test.client import RequestFactory from django.conf import settings -import logging -import io -import os logger = logging.getLogger("bornhack.%s" % __name__) @@ -36,7 +37,14 @@ def generate_pdf_letter(filename, template, formatdict): # get watermark from watermark file 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 @@ -60,4 +68,3 @@ def generate_pdf_letter(filename, template, formatdict): returnfile = io.BytesIO() finalpdf.write(returnfile) return returnfile - diff --git a/src/utils/management/commands/bootstrap-devsite.py b/src/utils/management/commands/bootstrap-devsite.py index ed9420a4..dba2109f 100644 --- a/src/utils/management/commands/bootstrap-devsite.py +++ b/src/utils/management/commands/bootstrap-devsite.py @@ -48,6 +48,7 @@ class Command(BaseCommand): timezone.datetime(2016, 9, 4, 12, 0, tzinfo=timezone.utc), timezone.datetime(2016, 9, 6, 12, 0, tzinfo=timezone.utc), ), + colour='#000000', ) 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, 6, 12, 0, tzinfo=timezone.utc), ), + colour='#000000', ) 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, 6, 12, 0, tzinfo=timezone.utc), ), + colour='#000000', ) self.output("Creating users...") From ee8c9cf01c7af7e91c421eb2f4b5282be64152b9 Mon Sep 17 00:00:00 2001 From: Stephan Telling Date: Thu, 17 Aug 2017 17:53:45 +0200 Subject: [PATCH 4/5] mend --- .../migrations/0048_product_ticket_type.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/shop/migrations/0048_product_ticket_type.py diff --git a/src/shop/migrations/0048_product_ticket_type.py b/src/shop/migrations/0048_product_ticket_type.py new file mode 100644 index 00000000..97c36ff6 --- /dev/null +++ b/src/shop/migrations/0048_product_ticket_type.py @@ -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'), + ), + ] From eac39352cd6174e014f0d6e639fd0aa6b7b80a39 Mon Sep 17 00:00:00 2001 From: Stephan Telling Date: Thu, 17 Aug 2017 18:38:25 +0200 Subject: [PATCH 5/5] move generate_pdf_letter func to utils app --- src/shop/invoiceworker.py | 2 +- src/tickets/models.py | 2 +- src/{shop => utils}/pdf.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/{shop => utils}/pdf.py (100%) diff --git a/src/shop/invoiceworker.py b/src/shop/invoiceworker.py index 52ce8e45..5ada3ff8 100644 --- a/src/shop/invoiceworker.py +++ b/src/shop/invoiceworker.py @@ -1,5 +1,5 @@ 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.models import Order, CustomOrder, Invoice, CreditNote import logging diff --git a/src/tickets/models.py b/src/tickets/models.py index 923d9ff7..1f59a4cb 100644 --- a/src/tickets/models.py +++ b/src/tickets/models.py @@ -13,7 +13,7 @@ from utils.models import ( UUIDModel, CreatedUpdatedModel ) -from shop.pdf import generate_pdf_letter +from utils.pdf import generate_pdf_letter logger = logging.getLogger("bornhack.%s" % __name__) diff --git a/src/shop/pdf.py b/src/utils/pdf.py similarity index 100% rename from src/shop/pdf.py rename to src/utils/pdf.py