List and display tickets (close #6)

This commit is contained in:
Víðir Valberg Guðmundsson 2016-05-31 00:58:11 +02:00
parent 093f9bddf9
commit aa3a3c0428
12 changed files with 161 additions and 11 deletions

View file

@ -59,6 +59,7 @@ TEMPLATES = [
'django.contrib.messages.context_processors.messages', 'django.contrib.messages.context_processors.messages',
'camps.context_processors.current_camp', 'camps.context_processors.current_camp',
'shop.context_processors.current_order', 'shop.context_processors.current_order',
'shop.context_processors.user_has_tickets',
], ],
}, },
}, },

View file

@ -106,6 +106,6 @@ footer {
padding: 5px; padding: 5px;
} }
.breadcrumb > li.pull-right::before { .breadcrumb > li.no-before::before {
content: ""; content: "";
} }

View file

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-05-30 22:23
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('news', '0001_initial'),
]
operations = [
migrations.AlterModelOptions(
name='newsitem',
options={'ordering': ['-published_at']},
),
]

View file

@ -1,3 +1,6 @@
from django.conf import settings
def current_order(request): def current_order(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
order = None order = None
@ -10,3 +13,10 @@ def current_order(request):
return {} return {}
def user_has_tickets(request):
has_tickets = False
if request.user.orders.filter(
tickets__product__category__pk=settings.TICKET_CATEGORY_ID
).exists():
has_tickets = True
return {'has_tickets': has_tickets}

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-05-30 22:23
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('shop', '0020_auto_20160530_1824'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='email',
field=models.EmailField(blank=True, max_length=254, null=True),
),
]

View file

@ -288,8 +288,8 @@ class CoinifyAPICallback(CreatedUpdatedModel):
class Ticket(CreatedUpdatedModel, UUIDModel): class Ticket(CreatedUpdatedModel, UUIDModel):
order = models.ForeignKey('shop.Order') order = models.ForeignKey('shop.Order', related_name='tickets')
product = models.ForeignKey('shop.Product') product = models.ForeignKey('shop.Product', related_name='tickets')
qrcode_base64 = models.TextField(null=True, blank=True) qrcode_base64 = models.TextField(null=True, blank=True)
name = models.CharField( name = models.CharField(
@ -300,6 +300,11 @@ class Ticket(CreatedUpdatedModel, UUIDModel):
), ),
) )
email = models.EmailField(
null=True,
blank=True,
)
def __str__(self): def __str__(self):
return 'Ticket {user} {product}'.format( return 'Ticket {user} {product}'.format(
user=self.order.user, user=self.order.user,
@ -321,12 +326,18 @@ class Ticket(CreatedUpdatedModel, UUIDModel):
).hexdigest() ).hexdigest()
def get_qr_code(self): def get_qr_code(self):
qr = qrcode.make(self.get_token()) qr = qrcode.make(
self.get_token(),
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H
).resize((250,250))
file_like = io.BytesIO() file_like = io.BytesIO()
qr.save(file_like) qr.save(file_like, format='png')
qrcode_base64 = base64.b64encode(file_like.getvalue()) qrcode_base64 = base64.b64encode(file_like.getvalue())
return qrcode_base64 return qrcode_base64
def get_qr_code_url(self): def get_qr_code_url(self):
return 'data:image/png;base64,{}'.format(self.qrcode_base64) 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}))

View file

@ -6,12 +6,12 @@
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-8"> <div class="col-sm-12 col-md-8">
<h2>{{ product.name }}</h2> <h2>{{ product.name }}</h2>
{{ product.description|commonmark }} {{ product.description|commonmark }}
</div> </div>
<div class="col-xs-12 col-md-4"> <div class="col-sm-12 col-md-4">
<h3>Add to order</h3> <h3>Add to order</h3>

View file

@ -13,7 +13,10 @@
<li class="active">{{ current_category }}</li> <li class="active">{{ current_category }}</li>
{% endif %} {% endif %}
{% if user.is_authenticated and user.orders.exists %} {% if user.is_authenticated and user.orders.exists %}
<li class="pull-right"><a href="{% url 'shop:order_list' %}">Previous orders</a></li> {% if has_tickets %}
<li class="pull-right"><a href="{% url 'shop:ticket_list' %}">Tickets</a></li>
{% endif %}
<li class="pull-right no-before"><a href="{% url 'shop:order_list' %}">Orders</a></li>
{% endif %} {% endif %}
</ol> </ol>
</div> </div>

View file

@ -0,0 +1,39 @@
{% extends 'shop_base.html' %}
{% load bootstrap3 %}
{% load shop_tags %}
{% block shop_content %}
<div class="well">
<div class="row">
<div class="col-md-5" style="text-align: center;">
<h3>{{ ticket.product.name }} ticket</h3>
<div style="margin:0px auto;width:250px;height:250px;background-image:url({{ ticket.get_qr_code_url }});"></div>
</div>
<div class="col-md-7">
<div class="pull-right">
<h2>{{ ticket.order.camp }}</h2>
<form method="POST" class="form">
{% csrf_token %}
{% bootstrap_field form.name %}
{% bootstrap_field form.email %}
<button class="btn btn-primary form-control" type="submit"><i class="glyphicon glyphicon-check"></i> Save</button>
</form>
<hr />
<div class="pull-right">
<a href="#" class="btn btn-default">Answer questionnaire</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -3,9 +3,38 @@
{% load shop_tags %} {% load shop_tags %}
{% block shop_content %} {% block shop_content %}
<h3>Tickets</h3>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>
Ticket owner
<th>
Product name
<th>
Price
<tbody>
{% for ticket in tickets %} {% for ticket in tickets %}
{{ ticket }} <tr>
<td>
<a href="{% url 'shop:ticket_detail' pk=ticket.pk %}" class="btn">
{% if ticket.name %}
{{ ticket.name }}
{% else %}
Click here to set the owner of this ticket
{% endif %}
</a>
<td>
<a href="{% url 'shop:ticket_detail' pk=ticket.pk %}" class="btn">
{{ ticket.product.name }}
<i class="glyphicon glyphicon-eye"></i>
</a>
<td>
{{ ticket.product.price|currency }}
{% endfor %} {% endfor %}
</table>
{% endblock %} {% endblock %}

View file

@ -21,6 +21,7 @@ urlpatterns = [
url(r'orders/(?P<pk>[0-9]+)/pay/banktransfer/$', BankTransferView.as_view(), name='bank_transfer'), url(r'orders/(?P<pk>[0-9]+)/pay/banktransfer/$', BankTransferView.as_view(), name='bank_transfer'),
url(r'tickets/$', TicketListView.as_view(), name='ticket_list'), url(r'tickets/$', TicketListView.as_view(), name='ticket_list'),
url(r'tickets/(?P<pk>\b[0-9A-Fa-f]{8}\b(-\b[0-9A-Fa-f]{4}\b){3}-\b[0-9A-Fa-f]{12}\b)$', TicketDetailView.as_view(), name='ticket_detail'),
url(r'privacy-policy/$', TemplateView.as_view(template_name='law/privacy_policy.html'), name='privacy-policy'), 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'return-policy/$', TemplateView.as_view(template_name='law/return_policy.html'), name='return-policy'),

View file

@ -11,6 +11,7 @@ from django.views.generic import (
ListView, ListView,
DetailView, DetailView,
FormView, FormView,
UpdateView,
) )
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.views.generic.detail import SingleObjectMixin from django.views.generic.detail import SingleObjectMixin
@ -486,3 +487,19 @@ class TicketListView(LoginRequiredMixin, ListView):
user = self.request.user user = self.request.user
return tickets.filter(order__user=user) return tickets.filter(order__user=user)
class TicketDetailView(LoginRequiredMixin, UpdateView, DetailView):
model = Ticket
template_name = 'ticket_detail.html'
context_object_name = 'ticket'
fields = ['name', 'email']
def form_valid(self, form):
messages.info(self.request, 'Ticket updated!')
return super(TicketDetailView, self).form_valid(form)
def dispatch(self, request, *args, **kwargs):
ticket = self.get_object()
if ticket.order.user != request.user:
return Http404
return super(TicketDetailView, self).dispatch(request, *args, **kwargs)