Changeset - 4162ba7c3fb0
[Not reviewed]
Merge
0 5 3
James Polley - 6 years ago 2018-04-17 05:54:38
jp@jamezpolley.com
Merge branch 'master' into ticket-testing
5 files changed with 28 insertions and 10 deletions:
0 comments (0 inline, 0 general)
pinaxcon/templates/symposion/schedule/_grid.html
Show inline comments
 

	
 
{% load lca2018_tags %}
 
{% load waffle_tags %}
 
<table class="calendar table table-bordered">
 
  <thead>
 
    <tr>
 
      <th class="time">&nbsp;</th>
 
        {% for room in timetable.rooms %}
 
          <th>{{ room.name }}</th>
 
          {% endfor %}
 
    </tr>
 
    {% with timetable|day_has_tracks:timetable.day as has_tracks %}
 
      {% if has_tracks %}
 
        <tr>
 
          <th class="time">&nbsp;</th>
 
          {% for room in timetable.rooms %}
 
            {% with room|trackname:timetable.day as track_name %}
 
              <th class="track-name">{% if track_name %}<p>{{ track_name }}{% endif %}</th>
 
	        {% endwith %}
 
            {% endwith %}
 
          {% endfor %}
 
        </tr>
 
      {% endif %}
 
    {% endwith %}
 
  </thead>
 
  <tbody>
 
    {% for row in timetable %}
 
      <tr>
 
        <td class="time"><h4>{{ row.time|date:"h:iA" }}</h4></td>
 
        {% for slot in row.slots %}
 
          <td class="slot slot-{{ slot.kind.label }}" colspan="{{ slot.colspan }}" rowspan="{{ slot.rowspan }}">
 
            {% if slot.kind.label == "talk" or slot.kind.label == "tutorial" %}
 
              {% if not slot.content %}
 
              {% else %}
 
                <span class="title">
 
                  <a href="{% url "schedule_presentation_detail" slot.content.pk %}">{{ slot.content.title }}</a>
 
                </span>
 
                <span class="speaker">
 
                  {{ slot.content.speakers|join:", " }}
 
                </span>
 
                {% flag "session_chair" %}
 
                  {% if slot.sessions %}
 
                    <div>
 
                      {% for session in slot.sessions.all %}
 
                        <em>Session chair:
 
                        {% if not session.chair %}
 
                          <a href="{% url "schedule_session_detail" session.id %}">Volunteer! 🙋</a>
 
                        {% else %}
 
                          <a href="{% url "schedule_session_detail" session.id %}">{{ session.chair.user.attendee.attendeeprofilebase.attendeeprofile.name }}</a>
 
                        {% endif %}</em>
 
                      {% endfor %}
 
                    </div>
 
                  {% endif %}
 
                {% endflag %}
 
              {% endif %}
 
            {% elif slot.kind.label == "shortbreak" %}
 
            {% else %}
 
              {% if slot.content_override %}
 
                {{ slot.content_override_html|safe }}
 
              {% else %}
 
                {{ slot.kind.label }}
 
              {% endif %}
 
            {% endif %}
 
            {% if "break" in slot.kind.label %}
 
            {% else %}
 
              <span class="room">
 
                {{ slot.rooms|join:", "}}<span class="endtime"> ends {{ slot.end|date:"h:iA" }}</span>
 
              </span>
 
            {% endif %}
 
          </td>
 
        {% endfor %}
 
        {% if forloop.last %}
 
          <td colspan="{{ timetable.rooms|length }}"></td>
vendor/regidesk/regidesk/models.py
Show inline comments
...
 
@@ -77,54 +77,58 @@ class CheckIn(models.Model):
 
    needs_review = models.BooleanField(default=False)
 
    review_text = models.TextField(blank=True)
 

	
 
    class Meta:
 
        permissions = (
 
            ("view_checkin_details", "Can view the details of other user's checkins"),
 
        )
 

	
 
    def save(self, *a, **k):
 
        while not self.checkin_code:
 
            checkin_code = generate_code()
 
            if CheckIn.objects.filter(checkin_code=checkin_code).count() == 0:
 
                self.checkin_code = checkin_code
 
        return super(CheckIn, self).save(*a, **k)
 

	
 
    def mark_checked_in(self):
 
        self.checked_in_bool = True
 
        self.checked_in = timezone.now()
 
        self.save()
 

	
 
    def mark_badge_printed(self):
 
        self.badge_printed = True
 
        self.save()
 

	
 
    def unset_badge(self):
 
        self.badge_printed = False
 
        self.save()
 

	
 
    def mark_schwag_given(self):
 
        self.schwag_given = True
 
        self.save()
 

	
 
    def bulk_mark_given(self):
 
        self.badge_printed = True
 
        self.checked_in_bool = True
 
        self.schwag_given = True
 
        self.save()
 

	
 
    def set_exception(self, text):
 
        self.needs_review = True
 
        self.review_text = text
 
        self.save()
 

	
 
    @property
 
    def code(self):
 
        return self.checkin_code
 

	
 
    @property
 
    def qrcode(self):
 
        """Returns the QR Code for this checkin's code.
 

	
 
        If this is the first time the QR code has been generated, cache it on the object.
 
        If a code has already been cached, serve that.
 

	
 
        Returns the raw PNG blob, unless b64=True, in which case the return value
 
        is the base64encoded PNG blob."""
 

	
 
        if not self.code:
 
            return None
vendor/regidesk/regidesk/templates/regidesk/boardingpass_overview.html
Show inline comments
...
 
@@ -47,49 +47,50 @@
 
            </select>
 
            <br/>
 
            <button id="next-button" type="submit" class="btn btn-primary" disabled>Next <i class="fa fa-chevron-right"></i></button>
 
        </p>
 

	
 
        <table class="table table-striped table-bordered dataTable">
 
            <thead>
 
                <th><input type="checkbox" id="action-toggle"></th>
 
                <th class="toggle">#</th>
 
                <th>Attendee Name</th>
 
                <th>Ticket Type</th>
 
                <th class="toggle">Attendee email</th>
 
                <th class="toggle">Checkin Code</th>
 
                <th>Notified?</th>
 
            </thead>
 

	
 
            <tbody>
 
                {% for attendee in attendees %}
 
                    <tr>
 
                        <td><input class="action-select" type="checkbox" name="_selected_action" value="{{ attendee.pk }}"></td>
 
                        <td>{{ attendee.id }}</td>
 
                        <td>{{ attendee.attendeeprofilebase.attendeeprofile.name }}</td>
 
                        <td>{{ attendee.ticket_type }}</td>
 
                        <td>{{ attendee.user.email }}</td>
 
                        <td><a href="{% url 'regidesk:check_in_user_view' attendee.user.checkin.code %}">{{ attendee.user.checkin.code }}</a></td>
 
                        <td>{% if attendee.user.checkin.code %}
 
                            <a href="{% url 'regidesk:check_in_user_view' attendee.user.checkin.code %}">{{ attendee.user.checkin.code }}</a>{% endif %}</td>
 
                        <td>
 
                            {% if attendee.user.checkin %}
 
                              {% if attendee.user.checkin.boardingpass %}
 
                                Boarding pass sent<br/>
 
                              {% else %}
 
                                Checkin Created
 
                              {% endif %}
 
                            {% else %}
 
                              Pending
 
                            {% endif %}
 
                        </td>
 
                    </tr>
 
                {% endfor %}
 
            </tbody>
 
        </table>
 
    </form>
 
{% endblock %}
 

	
 
{% block extra_script %}
 
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs/jszip-2.5.0/dt-1.10.16/b-1.4.2/b-colvis-1.4.2/b-flash-1.4.2/b-html5-1.4.2/b-print-1.4.2/cr-1.4.1/fc-3.2.3/fh-3.1.3/r-2.2.0/rg-1.0.2/datatables.min.css"/>
 
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.min.js"></script>
 
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js"></script>
 
<script type="text/javascript" src="https://cdn.datatables.net/v/bs/jszip-2.5.0/dt-1.10.16/b-1.4.2/b-colvis-1.4.2/b-html5-1.4.2/b-print-1.4.2/cr-1.4.1/fc-3.2.3/fh-3.1.3/r-2.2.0/rg-1.0.2/datatables.min.js"></script>
 
    <script type="text/javascript">
vendor/regidesk/regidesk/templates/regidesk/ci_overview.html
Show inline comments
...
 
@@ -10,111 +10,117 @@
 
    {% load registrasion_tags %}
 
    {% load lca2018_tags %}
 
    {% items_purchased as purchased %}
 
    {% items_pending as pending %}
 
    {% items_purchased 1 as ticket %}
 
    {% items_purchased 6 as shirts %}
 
    {% total_items_purchased 3 as penguin_dinner_count %}
 
    {% total_items_purchased 4 as speakers_dinner_count %}
 
    {% total_items_purchased 5 as pdns_count %}
 
    {% ticket_type as ticket_type %}
 

	
 
    <div class="panel panel-default">
 
        <div class="panel-heading">Content Check</div>
 
        <div class="panel-body">
 
            <dl class="dl-horizontal">
 
                <dt>Ticket type</dt><dd>{{ ticket_type }}</dd>
 
                <dt>Name</dt><dd>{{ user.attendee.attendeeprofilebase.attendeeprofile.name }}</dd>
 
                <dt>Company</dt><dd>{% if ticket_type == "Student" or ticket_type == "Hobbyist" or "Only" in ticket_type %}{% else %}{{ user.attendee.attendeeprofilebase.attendeeprofile.company }}{% endif %}</dd>
 
                <dt>Free Text 1</dt><dd>{{ user.attendee.attendeeprofilebase.attendeeprofile.free_text_1 }}</dd>
 
                <dt>Free Text 2</dt><dd>{{ user.attendee.attendeeprofilebase.attendeeprofile.free_text_2 }}</dd>
 
                <dt>Penguin Dinner Tickets</dt><dd>{{ penguin_dinner_count }}</dd>
 
                <dt>Spearker Dinner Tickets</dt><dd>{{ speakers_dinner_count }}</dd>
 
                <dt>PDNS Tickets</dt><dd>{{ pdns_count }}</dd>
 
                <dt>Over 18 years</dt><dd>{% if user.attendee.attendeeprofilebase.attendeeprofile.of_legal_age %}yes{% else %}<strong class="red">NO</strong>{% endif %}</dd>
 
                <dt>Username</dt><dd>{{ user.username }}</dd>
 
            </dl>
 
            <table class="table table-striped">
 
                <tr>
 
                    <th>item</th>
 
                    <th>count</th>
 
                </tr>
 
                {% for shirt in shirts%}
 
                    <tr>
 
                        <td>{{ shirt.product }}</td>
 
                        <td>{{ shirt.quantity }}</td>
 
                    </tr>
 
                {% endfor %}
 
            </table>
 
        </div>
 
    </div>
 

	
 
    <div class="panel {% if check_in.checked_in_bool %}panel-danger{% else %}panel-success{% endif %}">
 
        <div class="panel-heading">Check In</div>
 
        <div class="panel-body">
 
            <dl class="dl-horizontal">
 
                <dt>Status</dt><dd>{% if check_in.checked_in_bool %}Checked in{% else %}Not checked in{% endif %}</dd>
 
            </dl>
 
            <blockquote>
 
                <p>If an attendee sees an error with their contents, please instruct them to change their profile and come back before checking them in.</p>
 
                <p>The attendee will be unable to edit their profile after they have been checked in</p>
 
            </blockquote>
 
            <form method="post">
 
                <input type="checkbox" name="checkin" value="checkin" checked hidden>
 
                <input class="btn {% if check_in.badge_printed %}btn-danger{% else %}btn-success{% endif %} pull-right" type="submit" value="Submit">
 
            </form>
 
        </div>
 
    </div>
 

	
 

	
 
    <div class="panel {% if check_in.badge_printed %}panel-danger{% else %}panel-success{% endif %}">
 
        <div class="panel-heading">Badge</div>
 
        <div class="panel-body">
 
            <dl class="dl-horizontal">
 
                <dt>Status</dt><dd>{% if check_in.badge_printed %}Marked{% else %}Not marked{% endif %} as printed</dd>
 
            </dl>
 
            <form method="post">
 
            <form method="post" hidden>
 
                <input type="checkbox" name="badge" value="badge" checked hidden>
 
                <a type="button" class="btn btn-primary" href="badge">Show Badge</a>
 
                <input class="btn {% if check_in.badge_printed %}btn-danger{% else %}btn-success{% endif %} pull-right" type="submit" value="Submit">
 
            </form>
 
            <form method="post">
 
                <input type="checkbox" name="unbadge" value="unbadge" checked hidden>
 
                <input class="btn btn-danger pull-right" type="submit" value="Force Reprint">
 
            </form>
 
        </div>
 
    </div>
 

	
 
    <div class="panel {% if check_in.schwag_given %}panel-danger{% else %}panel-success{% endif %}">
 
        <div class="panel-heading">Schwag</div>
 
        <div class="panel-body">
 
            <dl class="dl-horizontal">
 
                <dt>Status</dt><dd>{% if check_in.schwag_given %}Marked{% else %}Not marked{% endif %} as given</dd>
 
            </dl>
 
            <form method="post">
 
                <input type="checkbox" name="schwag" value="schwag" checked hidden>
 
                <input class="btn {% if check_in.schwag_given %}btn-danger{% else %}btn-success{% endif %} pull-right" type="submit" value="Submit">
 
            </form>
 
        </div>
 
    </div>
 

	
 
    <div class="panel panel-warning">
 
        <div class="panel-heading">Log Exception</div>
 
        <div class="panel-body">
 
            <form method="post">
 
                <textarea class="form-control" rows="3" name="exception">{{ check_in.review_text }}</textarea>
 
                <p class="help-block">Reminder: Please tell attendee to email boarding@lca2018.org with the details as well</p>
 
                <input class="btn btn-warning pull-right" type="submit" value="Submit">
 
            </form>
 
        </div>
 
    </div>
 

	
 
    <div class="panel {% if check_in.badge_printed or check_in.schwag_given %}panel-danger{% else %}panel-success{% endif %}">
 
    <div class="panel {% if check_in.checked_in_bool or check_in.schwag_given %}panel-danger{% else %}panel-success{% endif %}">
 
        <div class="panel-heading">Bulk actions</div>
 
        <div class="panel-body">
 
            <p>Mark attendee as checked in and schwag given</p>
 
            <dl class="dl-horizontal">
 
                <dt>Status</dt><dd>{% if check_in.badge_printed or check_in.schwag_given %}One of the items in bulk action is marked as given already{% else %}Both items are marked as unrecived{% endif %}</dd>
 
                <dt>Status</dt><dd>{% if check_in.checked_in_bool or check_in.schwag_given %}One of the items in bulk action is marked as given already{% else %}Both items are marked as unrecived{% endif %}</dd>
 
            </dl>
 
            <form method="post">
 
                <input type="checkbox" name="bulk" value="bulk" checked hidden>
 
                <input class="btn  {% if check_in.badge_printed or check_in.schwag_given %}btn-danger{% else %}btn-success{% endif %} pull-right" type="submit" value="Submit">
 
                <input class="btn  {% if check_in.checked_in_bool or check_in.schwag_given %}btn-danger{% else %}btn-success{% endif %} pull-right" type="submit" value="Submit">
 
            </form>
 
        </div>
 
    </div>
 
    <a type=button" class="btn btn-primary btn-lg" href="{% url 'regidesk:check_in_scanner' %}">Return to scanning page</a>
 

	
 
{% endblock %}
vendor/regidesk/regidesk/views.py
Show inline comments
...
 
@@ -31,78 +31,81 @@ 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:
 
        templates = BoardingPassTemplate.objects.all()
 
        if not templates:
 
            messages.add_message(request, messages.WARNING,
 
                                 'Your boarding pass has not been prepared and I can\'t find a '
 
                                 'default template to use. This page has similar information to '
 
                                 'the boarding pass - please check back later.')
 
            return redirect('/tickets/review')
 
        prepare_boarding_pass(request, templates[0])
 
        prepare_boarding_pass(request.user, templates[0])
 
        checkin = CheckIn.objects.get_or_create(user=user)[0]
 

	
 
    boardingpass = checkin.boardingpass
 
    qrcode_url = request.build_absolute_uri(reverse("regidesk:checkin_png", args=[checkin.code]))
 
    qrcode = checkin.qrcode
 
    qrcode_string ='<img src="data:image/png;base64,' + qrcode + '"/>'
 
    not_qrcode_string = '<img src="cid:qrcode.png"/>'
 

	
 
    boardingpass_body = boardingpass.html_body.replace(not_qrcode_string, qrcode_string)
 
    ctx = { 'attendee': user.attendee,
 
            'boardingpass_body': boardingpass_body,
 
            '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 }
 
    print(datetime.now())
 
    ticketholders = ( ticket.invoice.user for ticket in tickets )
 
    print(datetime.now())
 

	
 
    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,
 
    }
 

	
...
 
@@ -173,49 +176,49 @@ def boarding_prepare(request):
 
        rendered_template['html'] = Template(bp_template.html_body).render(ctx)
 
        request.session['template'] = bp_template.pk
 
    else:
 
        subject = None
 
        request.session['template'] = 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
 
    return render(request, "regidesk/boardingpass_prepare.html", ctx)
 

	
 
def prepare_boarding_pass(user, template, attendee=None):
 

	
 
    if attendee:
 
        user = attendee.user
 
    else:
 
        user = request.user
 
        user = user
 
        attendee=user.attendee
 
    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])),
 
        "qrcode_url": "https://rego.linux.conf.au/checkin/" + user.checkin.code + ".png"
 
    }
 
    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
 

	
...
 
@@ -291,48 +294,50 @@ class CheckInLanding(PermissionRequiredMixin, TemplateView):
 
    permission_required = 'regidesk.view_boarding_pass'
 

	
 

	
 
@csrf_exempt
 
@permission_required("regidesk.view_boarding_pass")
 
def check_in_overview(request, access_code):
 
    check_in = CheckIn.objects.filter(
 
        checkin_code=access_code,
 
    )
 
    if not check_in:
 
        # yea it's a 200...
 
        return render(request, "regidesk/ci_code_404.html", {})
 
    check_in = check_in[0]
 
    if request.method == 'POST':
 
        if 'checkin' in request.POST:
 
            check_in.mark_checked_in()
 
        elif 'badge' in request.POST:
 
            check_in.mark_badge_printed()
 
        elif 'schwag' in request.POST:
 
            check_in.mark_schwag_given()
 
        elif 'bulk' in request.POST:
 
            check_in.bulk_mark_given()
 
        elif 'exception' in request.POST:
 
            check_in.set_exception(request.POST['exception'])
 
        elif 'unbadge' in request.POST:
 
            check_in.unset_badge()
 
        return redirect(request.path)
 
    ctx = {
 
        'check_in': check_in,
 
        'user': check_in.user,
 
    }
 
    return render(request, "regidesk/ci_overview.html", ctx)
 

	
 

	
 
@permission_required("regidesk.view_boarding_pass")
 
def checken_in_badge(request, access_code):
 
    check_in = CheckIn.objects.filter(
 
        checkin_code=access_code,
 
    )
 
    if not check_in:
 
        # yea it's a 200...
 
        return render(request, "regidesk/ci_code_404.html", {})
 
    badge = render_badge(check_in[0].user, format="svg", overlay=True)
 
    return badge
 

	
 
@login_required
 
def redir_main(request):
 
    if request.user.has_perm('regidesk.view_boarding_pass'):
 
        return redirect(reverse('regidesk:boarding_overview'))
 
    return redirect(reverse('regidesk:boardingpass'))
0 comments (0 inline, 0 general)