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

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


@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
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 58
@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
59 60 61 62 63 64 65 66
@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 = (
67 68 69 70
        ['name', 'paid', 'present', 'email',
         'phone number'] +
        [field.name for field in extra_fields] +
        ['status', 'date', 'date cancelled'])
Thom Wiggers's avatar
Thom Wiggers committed
71 72 73

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

Thom Wiggers's avatar
Thom Wiggers committed
108 109 110 111 112 113 114 115 116 117
        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':
118
            return item['dateobj'] + timedelta(days=10000)
Thom Wiggers's avatar
Thom Wiggers committed
119
        elif item['status'] == 'registered':
120
            return item['dateobj'] - timedelta(days=10000)
Thom Wiggers's avatar
Thom Wiggers committed
121
        else:
122
            return item['dateobj']
123

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

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


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
    })
143 144 145 146 147 148 149


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

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

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

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

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


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

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

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

202 203 204 205 206 207 208 209 210 211 212
            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
213 214 215 216
            else:
                error_message = _("You were already registered.")

            if error_message is None:
217
                success_message = _("Registration successful.")
218 219 220 221 222
        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)):
223
            show_fields = True
224 225
            success_message = _("Registration successfully updated.")
        elif action == 'cancel':
226 227 228 229 230 231 232
            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()
233
                success_message = _("Registration successfully cancelled.")
234 235 236 237
            else:
                error_message = _("You were not registered for this event.")

        if show_fields:
238 239 240
            if request.POST:
                form = FieldsForm(request.POST, registration=obj)
                if form.is_valid():
241
                    obj.save()
242 243
                    form_field_values = form.field_values()
                    for field in form_field_values:
244 245 246 247
                        if (field['field'].type ==
                                RegistrationInformationField.INTEGER_FIELD
                                and field['value'] is None):
                            field['value'] = 0
248 249 250 251 252 253 254 255 256 257 258 259
                        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()
260 261

    return redirect(event)