import base64 import logging from datetime import datetime from email.mime.image import MIMEImage from django.core.exceptions import ValidationError from django.core.mail import EmailMultiAlternatives from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import permission_required, user_passes_test, login_required from django.contrib.auth.models import User, Group from django.db import transaction from django.db.models import F, Q from django.db.models import Count, Max, Sum from django.http import Http404 from django.http import HttpResponse, HttpResponseBadRequest from django.shortcuts import redirect, render from django.template import Template, Context from django.urls import reverse from registrasion import util from registrasion.models import commerce, people from registrasion.templatetags.registrasion_tags import items_purchased, items_pending from registrasion.templatetags.registrasion_tags import invoices, missing_categories from symposion.conference.models import Conference from regidesk import forms from regidesk.models import BoardingPass, BoardingPassTemplate, CheckIn AttendeeProfile = util.get_object_from_name(settings.ATTENDEE_PROFILE_MODEL) def _staff_only(user): ''' Returns true if the user is staff. ''' return user.is_staff @login_required def boardingpass(request): user=request.user checkin = CheckIn.objects.get_or_create(user=user)[0] if not checkin.boardingpass: messages.add_message(request, messages.WARNING, 'Your boarding pass has not been prepared. Please try again later.') return redirect('/') boardingpass = checkin.boardingpass.html_body qrcode_url = request.build_absolute_uri(reverse("regidesk:checkin_png", args=[checkin.code])) qrcode = checkin.qrcode qrcode_string ='' not_qrcode_string = '' boardingpass = boardingpass.replace(not_qrcode_string, qrcode_string) ctx = { 'attendee': user.attendee, 'boardingpass': boardingpass } response = render(request, "regidesk/boardingpass.html", ctx) return response @permission_required("regidesk.view_boarding_pass") def boarding_overview(request, boarding_state="pending"): tickets = commerce.LineItem.objects.select_related( "invoice","invoice__user__attendee","product__category" ).filter( invoice__status=commerce.Invoice.STATUS_PAID, product__category=settings.TICKET_PRODUCT_CATEGORY, price__gte=0 ) ticketholders = { ticket.invoice.user: ticket.product.name for ticket in tickets } attendees = people.Attendee.objects.select_related( "attendeeprofilebase", "attendeeprofilebase__attendeeprofile", "user", "user__checkin" ).filter(user__in=ticketholders) profiles = AttendeeProfile.objects.filter( attendee__in=attendees ).select_related( "attendee", "attendee__user", ) profiles_by_attendee = dict((i.attendee, i) for i in profiles) bp_templates = BoardingPassTemplate.objects.all() ctx = { "boarding_state": boarding_state, "attendees": attendees, "profiles": profiles_by_attendee, "templates": bp_templates, } return render(request, "regidesk/boardingpass_overview.html", ctx) @login_required def checkin_png(request, checkin_code): checkin = CheckIn.objects.get(checkin_code=checkin_code) if not checkin: raise Http404() if not request.user.has_perm("regidesk.view_checkin_details"): if request.user != checkin.user: raise Http404() response = HttpResponse() response["Content-Type"] = "image/png" response["Content-Disposition"] = 'inline; filename="qrcode.png"' qrcode = base64.b64decode(checkin.qrcode) response.write(qrcode) return response @permission_required("regidesk.send_boarding_pass") def boarding_prepare(request): attendee_pks = [] try: for pk in request.POST.getlist("_selected_action"): attendee_pks.append(int(pk)) except ValueError: return HttpResponseBadRequest() attendees = people.Attendee.objects.filter(pk__in=attendee_pks) attendees = attendees.select_related( "user", "attendeeprofilebase", "attendeeprofilebase__attendeeprofile") sample_checkin = CheckIn.objects.get_or_create(user=attendees[0].user)[0] rendered_template = {} sample_ctx = {} bp_template_pk = request.POST.get("template", "") if bp_template_pk: bp_template = BoardingPassTemplate.objects.get(pk=bp_template_pk) sample_ctx = { "user": sample_checkin.user, "boardingpass": sample_checkin.boardingpass, "code": sample_checkin.code, "qrcode": '', "qrcode_url": request.build_absolute_uri( reverse("regidesk:checkin_png", args=[sample_checkin.code])), } ctx = Context(sample_ctx) ctx["invoices"] = invoices(ctx) ctx["items_pending"] = items_pending(ctx) ctx["items_purchased"] = items_purchased(ctx) ctx["missing_categories"] = missing_categories(ctx) subject = Template(bp_template.subject).render(ctx) rendered_template['plain'] = Template(bp_template.body).render(ctx) rendered_template['html'] = Template(bp_template.html_body).render(ctx) else: bp_template = None subject = None ctx = { "attendees": attendees, "template": bp_template, "attendee_pks": attendee_pks, "rendered_template": rendered_template, "subject": subject, "sample": sample_ctx, } request.session.set_expiry=(300) request.session['boarding_attendees'] = attendee_pks request.session['template'] = bp_template.pk response = render(request, "regidesk/boardingpass_prepare.html", ctx) return response @permission_required("regidesk.send_boarding_pass") def boarding_send(request): BOARDING_GROUP = getattr(settings, "REGIDESK_BOARDING_GROUP", None) if BOARDING_GROUP and Group.objects.filter(name=BOARDING_GROUP): boarding_users = User.objects.filter(groups__name=BOARDING_GROUP) else: boarding_users = User.objects.all() attendees = people.Attendee.objects.filter(pk__in=request.session['boarding_attendees']) attendees = attendees.select_related( "user", "attendeeprofilebase", "attendeeprofilebase__attendeeprofile") logging.debug(attendees) template_pk = request.session['template'] template = BoardingPassTemplate.objects.get(pk=template_pk) for attendee in attendees: user = attendee.user checkin = CheckIn.objects.get_or_create(user=user) ctx = { "user": user, "checkin": user.checkin, "code": user.checkin.code, "qrcode": user.checkin.qrcode, "qrcode_url": request.build_absolute_uri( reverse("regidesk:checkin_png", args=[user.checkin.code])), } ctx = Context(ctx) ctx["invoices"] = invoices(ctx) ctx["items_pending"] = items_pending(ctx) ctx["items_purchased"] = items_purchased(ctx) ctx["missing_categories"] = missing_categories(ctx) subject = Template(template.subject).render(ctx) body = Template(template.body).render(ctx) if template.html_body: html_body = Template(template.html_body).render(ctx) else: html_body = None bpass = BoardingPass(template=template, to_address=user.email, from_address=template.from_address, subject=subject, body=body, html_body=html_body ) bpass.save() if user.checkin.boardingpass: user.checkin.boardingpass.delete() user.checkin.boardingpass = bpass user.checkin.save() msg = EmailMultiAlternatives( bpass.subject, bpass.body, bpass.from_address, [bpass.to_address,], ) msg.content_subtype="plain" msg.mixed_subtype="related" if bpass.html_body: msg.attach_alternative(bpass.html_body, "text/html") msg.attach(filename="qrcode.png", content=user.checkin.qrcode, mimetype="image/png") if user in boarding_users: with transaction.atomic(): msg.send() bpass.sent = datetime.now() bpass.save() messages.success(request, "Sent boarding pass to %s" % attendee) request.session['boarding_attendees'].remove(attendee.pk) return redirect("regidesk:boarding_overview")