views.py 9.11 KB
Newer Older
Thom Wiggers's avatar
Thom Wiggers committed
1
import csv
2
import json
Thom Wiggers's avatar
Thom Wiggers committed
3 4
from datetime import timedelta

5 6
from django.http import HttpResponse, JsonResponse
from django.views.decorators.http import require_http_methods
7 8
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
Thom Wiggers's avatar
Thom Wiggers committed
9
from django.contrib.admin.views.decorators import staff_member_required
10
from django.contrib.auth.decorators import permission_required, login_required
Thom Wiggers's avatar
Thom Wiggers committed
11 12
from django.utils import timezone
from django.utils.text import slugify
13
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
Thom Wiggers's avatar
Thom Wiggers committed
14

15
from .models import Event, Registration, RegistrationInformationField
16
from .forms import FieldsForm
Thom Wiggers's avatar
Thom Wiggers committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31


@staff_member_required
@permission_required('events.change_event')
def admin_details(request, event_id):
    event = get_object_or_404(Event, pk=event_id)
    n = event.max_participants
    registrations = list(event.registration_set.filter(date_cancelled=None))
    cancellations = event.registration_set.exclude(date_cancelled=None)
    return render(request, 'events/admin/details.html', {
        'event': event,
        'registrations': registrations[:n],
        'waiting': registrations[n:] if n else [],
        'cancellations': cancellations,
    })
Thom Wiggers's avatar
Thom Wiggers committed
32 33


34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
@staff_member_required
@permission_required('events.change_event')
@require_http_methods(["POST"])
def admin_change_registration(request, event_id, action=None):
    data = {
        'success': True
    }

    try:
        id = request.POST.get("id", -1)
        checked = json.loads(request.POST.get("checked"))
        obj = Registration.objects.get(event=event_id, pk=id)
        if checked is not None:
            if action == 'present':
                obj.present = checked
            elif action == 'paid':
                obj.paid = checked
            obj.save()
    except Registration.DoesNotExist:
        data['success'] = False

    return JsonResponse(data)


Thom Wiggers's avatar
Thom Wiggers committed
58 59 60 61 62 63 64 65
@staff_member_required
@permission_required('events.change_event')
def export(request, event_id):
    event = get_object_or_404(Event, pk=event_id)
    extra_fields = event.registrationinformationfield_set.all()
    registrations = event.registration_set.all()

    header_fields = (
66 67 68 69
        ['name', 'paid', 'present', 'email',
         'phone number'] +
        [field.name for field in extra_fields] +
        ['status', 'date', 'date cancelled'])
Thom Wiggers's avatar
Thom Wiggers committed
70 71 72

    rows = []
    capacity = event.max_participants
73 74
    if event.price == 0:
        header_fields.remove('paid')
Thom Wiggers's avatar
Thom Wiggers committed
75 76 77 78 79
    for i, registration in enumerate(registrations):
        if registration.member:
            name = registration.member.get_full_name()
        else:
            name = registration.name
80
        status = pgettext_lazy('registration status', 'registered')
Thom Wiggers's avatar
Thom Wiggers committed
81 82 83 84
        cancelled = None
        if registration.date_cancelled:
            if capacity is not None:
                capacity += 1
85
            status = pgettext_lazy('registration status', 'cancelled')
Thom Wiggers's avatar
Thom Wiggers committed
86 87
            cancelled = timezone.localtime(registration.date_cancelled)
        elif capacity and i >= capacity:
88
            status = pgettext_lazy('registration status', 'waiting')
Thom Wiggers's avatar
Thom Wiggers committed
89 90
        data = {
            'name': name,
91 92 93 94 95 96 97
            'date': timezone.localtime(registration.date
                                       ).strftime("%Y-%m-%d %H:%m"),
            'dateobj': registration.date,
            'present': _('Yes') if registration.present else '',
            'phone number': (registration.member.phone_number
                             if registration.member
                             else ''),
Thom Wiggers's avatar
Thom Wiggers committed
98 99 100 101
            'email': (registration.member.user.email
                      if registration.member
                      else ''),
            'status': status,
102
            'date cancelled': cancelled,
Thom Wiggers's avatar
Thom Wiggers committed
103
        }
104 105 106
        if event.price > 0:
            data['paid'] = _('Yes') if registration.paid else ''

Thom Wiggers's avatar
Thom Wiggers committed
107 108 109 110 111 112 113 114 115 116
        data.update({field['field'].name: field['value'] for field in
                     registration.registration_information()})
        rows.append(data)

    response = HttpResponse(content_type='text/csv')
    writer = csv.DictWriter(response, header_fields)
    writer.writeheader()

    def order(item):
        if item['status'] == 'cancelled':
117
            return item['dateobj'] + timedelta(days=10000)
Thom Wiggers's avatar
Thom Wiggers committed
118
        elif item['status'] == 'registered':
119
            return item['dateobj'] - timedelta(days=10000)
Thom Wiggers's avatar
Thom Wiggers committed
120
        else:
121
            return item['dateobj']
122

Thom Wiggers's avatar
Thom Wiggers committed
123
    for row in sorted(rows, key=order):
124 125 126
        r = row.copy()
        del r['dateobj']
        writer.writerow(r)
Thom Wiggers's avatar
Thom Wiggers committed
127 128 129 130

    response['Content-Disposition'] = (
        'attachment; filename="{}.csv"'.format(slugify(event.title)))
    return response
Luuk Scholten's avatar
Luuk Scholten committed
131 132 133 134 135 136 137 138 139 140 141


def index(request):
    upcoming_activity = Event.objects.filter(
        published=True,
        end__gte=timezone.now()
    ).order_by('end').first()

    return render(request, 'events/index.html', {
        'upcoming_activity': upcoming_activity
    })
142 143 144 145 146 147 148


def event(request, event_id):
    event = get_object_or_404(
        Event.objects.filter(published=True),
        pk=event_id
    )
149 150
    registrations = event.registration_set.filter(
        date_cancelled=None)[:event.max_participants]
151 152 153 154 155 156 157 158

    context = {
        'event': event,
        'registrations': registrations,
        'user': request.user,
    }

    if event.max_participants:
159
        perc = 100.0 * len(registrations) / event.max_participants
160 161 162 163 164 165 166 167
        context['registration_percentage'] = perc

    try:
        registration = Registration.objects.get(
            event=event,
            member=request.user.member
        )
        context['registration'] = registration
168
    except Registration.DoesNotExist:
169 170 171
        pass

    return render(request, 'events/event.html', context)
172 173 174 175 176 177 178 179 180


@login_required
def registration(request, event_id, action=None):
    event = get_object_or_404(
        Event.objects.filter(published=True),
        pk=event_id
    )

181 182
    if (event.status != Event.REGISTRATION_NOT_NEEDED and
            request.user.member.current_membership is not None):
183
        try:
184
            obj = Registration.objects.get(
185 186 187 188
                event=event,
                member=request.user.member
            )
        except Registration.DoesNotExist:
189
            obj = None
190 191 192 193

        success_message = None
        error_message = None
        show_fields = False
194 195 196 197
        if action == 'register' and (
            event.status == Event.REGISTRATION_OPEN or
            event.status == Event.REGISTRATION_OPEN_NO_CANCEL
        ):
198 199 200
            if event.has_fields():
                show_fields = True

201 202 203 204 205 206 207 208 209 210 211
            if obj is None:
                obj = Registration()
                obj.event = event
                obj.member = request.user.member
            elif obj.date_cancelled is not None:
                if obj.is_late_cancellation():
                    error_message = _("You cannot re-register anymore since "
                                      "you've cancelled after the deadline.")
                else:
                    obj.date = timezone.now()
                    obj.date_cancelled = None
212 213 214 215
            else:
                error_message = _("You were already registered.")

            if error_message is None:
216
                success_message = _("Registration successful.")
217 218 219 220 221
        elif (action == 'update' and
              event.has_fields() and
              obj is not None and
              (event.status == Event.REGISTRATION_OPEN or
               event.status == Event.REGISTRATION_OPEN_NO_CANCEL)):
222
            show_fields = True
223 224
            success_message = _("Registration successfully updated.")
        elif action == 'cancel':
225 226 227 228 229 230 231
            if (obj is not None and
                    obj.date_cancelled is None):
                # Note that this doesn't remove the values for the
                # information fields that the user entered upon registering.
                # But this is regarded as a feature, not a bug. Especially
                # since the values will still appear in the backend.
                obj.date_cancelled = timezone.now()
232
                success_message = _("Registration successfully cancelled.")
233 234 235 236
            else:
                error_message = _("You were not registered for this event.")

        if show_fields:
237 238 239
            if request.POST:
                form = FieldsForm(request.POST, registration=obj)
                if form.is_valid():
240
                    obj.save()
241 242
                    form_field_values = form.field_values()
                    for field in form_field_values:
243 244 245 246
                        if (field['field'].type ==
                                RegistrationInformationField.INTEGER_FIELD
                                and field['value'] is None):
                            field['value'] = 0
247 248 249 250 251 252 253 254 255 256 257 258
                        field['field'].set_value_for(obj,
                                                     field['value'])
            else:
                form = FieldsForm(registration=obj)
                context = {'event': event, 'form': form, 'action': action}
                return render(request, 'events/event_fields.html', context)

        if success_message is not None:
            messages.success(request, success_message)
        elif error_message is not None:
            messages.error(request, error_message)
        obj.save()
259 260

    return redirect(event)