Merge remote-tracking branch 'origin/feature/tickets' into feature/tickets

# Conflicts:
#	shop/models.py
#	shop/urls.py
This commit is contained in:
Thomas Steen Rasmussen 2016-05-25 22:53:02 +02:00
commit 6016a6b605
26 changed files with 287 additions and 24 deletions

View file

@ -98,3 +98,5 @@ BOOTSTRAP3 = {
EPAY_MERCHANT_NUMBER = env('EPAY_MERCHANT_NUMBER')
EPAY_MD5_SECRET = env('EPAY_MD5_SECRET')
TICKET_CATEGORY_ID = env('TICKET_CATEGORY_ID')

View file

@ -9,3 +9,4 @@ EMAIL_USE_TLS=True
EMAIL_FROM='noreply@example.com'
EPAY_MERCHANT_NUMBER=something
EPAY_MD5_SECRET=something
TICKET_CATEGORY_ID=''

View file

@ -86,3 +86,13 @@ a, a:active, a:focus {
height: 500px;
}
/* Footer */
footer {
position: fixed;
width: 700px;
text-align: center;
background-color: white;
bottom: 0px;
padding: 5px;
}

View file

@ -53,6 +53,7 @@
{% endif %}
<li><a href="{% url 'good-to-know' %}">Info</a></li>
<li><a href="{% url 'contact' %}">Contact</a></li>
{% if user.is_authenticated %}
<li><a href="{% url 'profiles:detail' %}">Profile</a></li>
<li><a href="{% url 'account_logout' %}">Logout</a></li>
@ -69,6 +70,11 @@
<div id="main" class="container container-fluid">
{% bootstrap_messages %}
{% block content %}{% endblock %}
<footer class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
{% block footer %}{% endblock %}
</div>
</footer>
</div>
{% bootstrap_javascript jquery=1 %}
</body>

View file

@ -0,0 +1,20 @@
{% extends 'base.html' %}
{% block content %}
<p>
The legal entity behind BornHack is:<br />
BornHack IVS c/o Thomas Steen Rasmussen<br />
Offenbachsvej 34, 2. tv.<br />
2450 Copenhagen SV<br />
Denmark<br />
CVR# 37666521<br />
</p>
<p>
Email us at info@bornhack.dk<br />
Tweet us at @bornhax<br />
Hit us up on IRC at #bornhack @ irc.baconsvin.org (TLS port 6697)<br />
</p>
{% endblock %}

View file

@ -21,6 +21,11 @@ urlpatterns = [
TemplateView.as_view(template_name='good_to_know.html'),
name='good-to-know'
),
url(
r'contact/',
TemplateView.as_view(template_name='contact.html'),
name='contact'
),
url(
r'^login/$',
LoginView.as_view(),

View file

@ -5,3 +5,5 @@ django-environ>=0.4.0
psycopg2>=2.6.1
PyPDF2>=1.25.1
django-wkhtmltopdf>=3.0.0
Pillow==3.2.0
qrcode==5.3

View file

@ -1,18 +1,19 @@
from django.contrib import admin
from .models import Order, ProductCategory, Product, OrderProductRelation, EpayCallback, EpayPayment
from . import models
admin.site.register(EpayCallback)
admin.site.register(EpayPayment)
admin.site.register(models.EpayCallback)
admin.site.register(models.EpayPayment)
@admin.register(ProductCategory)
@admin.register(models.ProductCategory)
class ProductCategoryAdmin(admin.ModelAdmin):
list_display = [
'name',
]
@admin.register(Product)
@admin.register(models.Product)
class ProductAdmin(admin.ModelAdmin):
list_display = [
'name',
@ -23,10 +24,17 @@ class ProductAdmin(admin.ModelAdmin):
class ProductInline(admin.TabularInline):
model = OrderProductRelation
model = models.OrderProductRelation
@admin.register(Order)
class TicketInline(admin.TabularInline):
model = models.Ticket
exclude = ['qrcode_base64']
@admin.register(models.Order)
class OrderAdmin(admin.ModelAdmin):
list_display = [
'user',
@ -44,5 +52,16 @@ class OrderAdmin(admin.ModelAdmin):
exclude = ['products']
inlines = [ProductInline]
inlines = [ProductInline, TicketInline]
actions = ['mark_order_as_paid']
def mark_order_as_paid(self, request, queryset):
for order in queryset.filter(paid=False):
order.mark_as_paid()
mark_order_as_paid.description = 'Mark order(s) as paid'
@admin.register(models.Ticket)
class TicketAdmin(admin.ModelAdmin):
pass

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-05-23 15:08
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('shop', '0011_auto_20160517_1902'),
]
operations = [
migrations.CreateModel(
name='Ticket',
fields=[
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='shop.Order')),
('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='shop.Product')),
],
options={
'abstract': False,
},
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-05-25 16:58
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('shop', '0012_ticket'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='qrcode_base64',
field=models.TextField(blank=True, null=True),
),
]

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-05-25 17:02
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('shop', '0013_ticket_qrcode_base64'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='name',
field=models.CharField(default='', help_text=b'Name of the person this ticket belongs to. This can be different from the buying user.', max_length=100),
preserve_default=False,
),
]

View file

@ -1,3 +1,4 @@
from django.conf import settings
from django.db import models
from django.db.models.aggregates import Sum
from django.contrib.postgres.fields import DateTimeRangeField, JSONField
@ -8,6 +9,12 @@ from django.core.urlresolvers import reverse_lazy
from bornhack.utils import CreatedUpdatedModel, UUIDModel
from .managers import ProductQuerySet
import hashlib
import io
import base64
import qrcode
class Order(CreatedUpdatedModel):
@ -101,6 +108,21 @@ class Order(CreatedUpdatedModel):
def get_absolute_url(self):
return str(reverse_lazy('shop:order_detail', kwargs={'pk': self.pk}))
def mark_as_paid(self):
self.paid = True
for order_product in self.orderproductrelation_set.all():
category_pk = str(order_product.product.category.pk)
print(order_product, category_pk, settings.TICKET_CATEGORY_ID)
if category_pk == settings.TICKET_CATEGORY_ID:
for _ in range(0, order_product.quantity):
ticket = Ticket(
order=self,
product=order_product.product,
)
ticket.save()
self.save()
class ProductCategory(CreatedUpdatedModel, UUIDModel):
class Meta:
@ -222,3 +244,47 @@ class CoinifyCallback(CreatedUpdatedModel):
def __str__(self):
return 'callback at %s' % self.created
class Ticket(CreatedUpdatedModel, UUIDModel):
order = models.ForeignKey('shop.Order')
product = models.ForeignKey('shop.Product')
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.'
),
)
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,
)
).hexdigest()
def get_qr_code(self):
qr = qrcode.make(self.get_token())
file_like = io.BytesIO()
qr.save(file_like)
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)

View file

@ -1,7 +1,7 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
<h2>Pay by Bank Transfer</h2>

View file

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
<form method="POST">
{% csrf_token %}

View file

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% extends "shop_base.html" %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
{% bootstrap_javascript jquery=1 %}
<script charset="UTF-8" src="https://ssl.ditonlinebetalingssystem.dk/integration/ewindow/paymentwindow.js" type="text/javascript"></script>
<script type="text/javascript">

View file

@ -1,7 +1,7 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
<h2>Thank you for your payment!</h2>
<p class="lead">
{% if order.paid %}

View file

@ -0,0 +1,16 @@
{% extends 'shop_base.html' %}
{% block shop_content %}
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<a href="{% url 'shop:privacy-policy' %}">Privacy Policy</a><br />
<a href="{% url 'shop:return-policy' %}">Return Policy</a><br />
<a href="{% url 'shop:general-terms' %}">General Terms & Conditions</a><br />
</div>
</div>
{% block law-content %}
{% endblock %}
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends 'law/base.html' %}
{# Forretningsbetingelser / General terms and conditions #}
{% block law-content %}
<h1>General Terms & Conditions</h1>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends 'law/base.html' %}
{# Privatlivspolitik / Privacy policy #}
{% block law-content %}
<h1>Privacy Policy</h1>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends 'law/base.html' %}
{# Returbetingelser / Return policy #}
{% block law-content %}
<h1>Return Policy</h1>
{% endblock %}

View file

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% load shop_tags %}
{% block content %}
{% block shop_content %}
<h1>Order #{{ order.id }}</h1>

View file

@ -1,7 +1,7 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
<h3>Orders</h3>
<table class="table table-bordered table-hover">
<thead>

View file

@ -1,7 +1,7 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% block content %}
{% block shop_content %}
<h2>{{ product.name }}</h2>

View file

@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% block content %}
{% block shop_content %}
{% endblock %}
{% endblock %}
{% block footer %}
<a href="{% url 'shop:privacy-policy' %}">Privacy Policy</a> |
<a href="{% url 'shop:return-policy' %}">Return Policy</a> |
<a href="{% url 'shop:general-terms' %}">General Terms & Conditions</a>
{% endblock %}

View file

@ -1,8 +1,8 @@
{% extends 'base.html' %}
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% load shop_tags %}
{% block content %}
{% block shop_content %}
<div class="row">
<div class="col-md-12">

View file

@ -18,4 +18,8 @@ urlpatterns = [
url(r'orders/(?P<pk>[0-9]+)/pay/blockchain/thanks/$', CoinifyThanksView.as_view(), name='coinify_thanks'),
url(r'orders/(?P<pk>[0-9]+)/pay/banktransfer/$', BankTransferView.as_view(), name='bank_transfer'),
url(r'privacy-policy/', TemplateView.as_view(template_name='law/privacy_policy.html'), name='privacy-policy'),
url(r'return-policy/', TemplateView.as_view(template_name='law/return_policy.html'), name='return-policy'),
url(r'general-terms-and-conditions/', TemplateView.as_view(template_name='law/general_terms_and_conditions.html'), name='general-terms')
]