diff --git a/src/backoffice/templates/index.html b/src/backoffice/templates/index.html index d6764c7a..19f97455 100644 --- a/src/backoffice/templates/index.html +++ b/src/backoffice/templates/index.html @@ -16,17 +16,14 @@
{% if perms.camps.infoteam_permission %}

Info Team

- -

Hand Out Products

-

Use this view to mark products such as merchandise, cabins, fridges and so on as handed out.

-
- -

Check-In Tickets

-

Use this view to check-in tickets when participants arrive.

-
- -

Hand Out Badges

-

Use this view to mark badges as handed out.

+
+

+ User stuff +

+

+ Use this to get everything related to a user +

{% endif %} diff --git a/src/backoffice/templates/user/order_all_actions.html b/src/backoffice/templates/user/order_all_actions.html new file mode 100644 index 00000000..8ccb85f6 --- /dev/null +++ b/src/backoffice/templates/user/order_all_actions.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} +{% load static from staticfiles %} + +{% block content %} + +Orders + +Tickets (incl. badges) + +Merchandise + +{% endblock content %} + diff --git a/src/backoffice/templates/user/search.html b/src/backoffice/templates/user/search.html new file mode 100644 index 00000000..7c75d026 --- /dev/null +++ b/src/backoffice/templates/user/search.html @@ -0,0 +1,90 @@ +{% extends 'base.html' %} +{% load static from staticfiles %} +{% load qrcode %} + +{% block content %} + +
+ {% csrf_token %} + +
+ +
+

Scan the ticket!

+ + + + +
+ +
+ +
+ +{% if ticket %} + {{ ticket }}
+
+ Checked in?: {{ ticket.checked_in }} + +
+
{% csrf_token %} + +
+ +
+
+ {% qr_code "clear" %} +
+ +
+ {% qr_code "check-in" %} +
+ +{% endif %} + + + + + +{% endblock content %} + diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index aa5165f9..a892343d 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -7,6 +7,9 @@ app_name = "backoffice" urlpatterns = [ path("", BackofficeIndexView.as_view(), name="index"), # infodesk + path( + "user/", include([path("", SearchForUser.as_view(), name="user_interaction")]) + ), path("product_handout/", ProductHandoutView.as_view(), name="product_handout"), path("badge_handout/", BadgeHandoutView.as_view(), name="badge_handout"), path("ticket_checkin/", TicketCheckinView.as_view(), name="ticket_checkin"), diff --git a/src/backoffice/views.py b/src/backoffice/views.py index 76e121b4..07cfbba2 100644 --- a/src/backoffice/views.py +++ b/src/backoffice/views.py @@ -1,6 +1,7 @@ import logging, os from itertools import chain +import qrcode from django.contrib.auth.mixins import PermissionRequiredMixin, UserPassesTestMixin from django.contrib.auth.models import User from django.views.generic import TemplateView, ListView, DetailView @@ -14,7 +15,7 @@ from django.conf import settings from django.core.files import File from camps.mixins import CampViewMixin -from shop.models import OrderProductRelation +from shop.models import OrderProductRelation, Invoice, Order from tickets.models import ShopTicket, SponsorTicket, DiscountTicket from profiles.models import Profile from program.models import SpeakerProposal, EventProposal @@ -345,7 +346,6 @@ class ReimbursementCreateView(CampViewMixin, EconomyTeamPermissionMixin, CreateV def dispatch(self, request, *args, **kwargs): """ Get the user from kwargs """ - print("inside dispatch() with method %s" % request.method) self.reimbursement_user = get_object_or_404(User, pk=kwargs["user_id"]) # get response now so we have self.camp available below @@ -544,3 +544,30 @@ class RevenueDetailView(CampViewMixin, EconomyTeamPermissionMixin, UpdateView): return redirect( reverse("backoffice:revenue_list", kwargs={"camp_slug": self.camp.slug}) ) + + +class SearchForUser(TemplateView): + template_name = "user/search.html" + + def post(self, request, **kwargs): + check_in_ticket_id = request.POST.get("check_in_ticket_id") + if check_in_ticket_id: + ticket_to_check_in = ShopTicket.objects.get(pk=check_in_ticket_id) + ticket_to_check_in.checked_in = True + ticket_to_check_in.save() + messages.info(request, "Ticket checked-in!") + + return super().get(request, **kwargs) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + ticket_token = self.request.POST.get("ticket_token") + if ticket_token: + try: + ticket = ShopTicket.objects.get(token=ticket_token[1:]) + context["ticket"] = ticket + except ShopTicket.DoesNotExist: + messages.warning(self.request, "Ticket not found!") + + return context diff --git a/src/tickets/migrations/0006_auto_20190616_1746.py b/src/tickets/migrations/0006_auto_20190616_1746.py new file mode 100644 index 00000000..f2fac385 --- /dev/null +++ b/src/tickets/migrations/0006_auto_20190616_1746.py @@ -0,0 +1,28 @@ +# Generated by Django 2.2.2 on 2019-06-16 15:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tickets', '0005_auto_20180318_0906'), + ] + + operations = [ + migrations.AddField( + model_name='discountticket', + name='token', + field=models.CharField(max_length=64, null=True), + ), + migrations.AddField( + model_name='shopticket', + name='token', + field=models.CharField(max_length=64, null=True), + ), + migrations.AddField( + model_name='sponsorticket', + name='token', + field=models.CharField(max_length=64, null=True), + ), + ] diff --git a/src/tickets/models.py b/src/tickets/models.py index 1f2e6cd7..5cd9312e 100644 --- a/src/tickets/models.py +++ b/src/tickets/models.py @@ -26,6 +26,7 @@ class BaseTicket(CampRelatedModel, UUIDModel): ticket_type = models.ForeignKey("TicketType", on_delete=models.PROTECT) checked_in = models.BooleanField(default=False) badge_handed_out = models.BooleanField(default=False) + token = models.CharField(max_length=64) class Meta: abstract = True @@ -34,10 +35,14 @@ class BaseTicket(CampRelatedModel, UUIDModel): def camp(self): return self.ticket_type.camp + def save(self, **kwargs): + self.token = self._get_token() + super().save(**kwargs) + def _get_token(self): return hashlib.sha256( "{_id}{secret_key}".format( - _id=self.pk, secret_key=settings.SECRET_KEY + _id=self.uuid, secret_key=settings.SECRET_KEY ).encode("utf-8") ).hexdigest() diff --git a/src/utils/templatetags/qrcode.py b/src/utils/templatetags/qrcode.py new file mode 100644 index 00000000..d09b8e5c --- /dev/null +++ b/src/utils/templatetags/qrcode.py @@ -0,0 +1,23 @@ +import base64 +import io + +import qrcode +from django import template +from django.utils.safestring import mark_safe + +register = template.Library() + + +@register.simple_tag +def qr_code(value): + stream = io.BytesIO() + img = qrcode.make("#" + value, box_size=5) + img.save(stream, "PNG") + data = base64.b64encode(stream.getvalue()) + + return mark_safe( + "
" + '' + "
{}
" + "
".format(data.decode(), value) + )